OBD2 BLE Communication - как отправлять AT команды и получать данные
У меня есть ключ OBD2, и мне нужно узнать скорость автомобиля (используя BLE и iOS-устройство). В документации, поставляемой с ключом, не упоминались службы и характеристики, но при некоторой отладке я обнаружил несколько. Назовем их сервисом 1, 2, 3.
- Служба 1 имеет одну характеристику со свойством Read и свойством WriteWithoutResponse
- Сервис 2 имеет одну характеристику: свойство Read и свойство Notify
- Сервис 3 имеет две характеристики: характеристика A со свойством Read и свойство Notify, а характеристика B со свойством Write и свойство WriteWithoutResponse
Как узнать, какие характеристики мне нужны для отправки AT-команд и получения соответствующих данных, а затем как инициировать эту связь. Я должен быть в состоянии получить скорость в частности. Заранее спасибо.
Я пробовал следующее, но ничего не произошло:
func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
for characteristic in service.characteristics! {
if characteristic.properties.contains(.notify) {
peripheral.setNotifyValue(true, for: characteristic)
}
if characteristic.properties.contains(.write) {
let commandString = "010D\r"
if let commandData = commandString.data(using: .utf8) {
peripheral.writeValue(commandData, for: characteristic, type: .withoutResponse)
peripheral.writeValue(commandData, for: characteristic, type: .withResponse)
}
}
}
}
А затем ожидая чего-то в:
func peripheral(_ peripheral: CBPeripheral, didUpdateNotificationStateFor characteristic: CBCharacteristic, error: Error?) {
if let value = characteristic.value {
let text = String(data: value, encoding: String.Encoding.utf8)
self.onNotifyReceived(text)
}
}
1 ответ
Прежде всего, если вы говорите, например, с помощью ELM327 - который является одним из наиболее распространенных чипов OBD2 - вам лучше не начинать с PID (например, 010D
), а точнее инициализируйте его AT
последовательность команд (подробности см. в соответствующем руководстве).
Следующий, peripheralDidUpdateNotificationState
неправильный метод делегата. Это срабатывает всякий раз, когда вы подписываетесь или отменяете подписку на признак, а не когда его значение изменяется. Вы хотите реализовать метод делегата peripheralDidUpdateValueForCharacteristic
вместо.
Тем не менее, проблема в том, что адаптеры OBD2 BLE не используют фиксированные профили GATT. Большинство (если не все) адаптеры BLE OBD2 работают так, что они предлагают одну услугу с одной или двумя характеристиками:
- Характеристика записи. Это то, где мобильное устройство может записывать свои AT-команды (в случае, например, ELM327) и PID.
- Характеристика уведомления. Это тот, где результаты от автомобиля (ECU) возвращаются.
Получив доступ к этим характеристикам, вы можете реализовать последовательный протокол OBD2 (например, используя очередь команд, которая записывает и ожидает ответа, прежде чем передать готовую команду на прикладной уровень).
Некоторые адаптеры BLE объединяют эти два свойства в одну. Если вы хотите поддерживать произвольные адаптеры, вам нужно будет добавить экран "выберите свой адаптер", где вы будете проверять найденные адаптеры, запоминать характеристики и затем общаться.
Таким образом, можно писать приложения, которые работают со всеми видами адаптеров BLE OBD2 и не только поддерживают выбранную группу поставщиков, например, таких как OBD2 Expert (Disclaimer: я являюсь автором этого программного обеспечения).