Разработка Android приложения для работы с OBDII протоколом

Original author: Ruslan Yanchyshyn@Lemberg Solutions
  • Translation
image

Почему это нужно для вашего автомобиля?


Задумывались ли вы над тем чтоб отобразить параметры работы вашего автомобиля в собственном Android приложении? Если да, тогда добро пожаловать под кат. Мы как раз будем обсуждать вопрос разработки подобного приложения.

Для начала давайте взглянем на протоколы, используемые для диагностики транспортных средств.
OBD — это сокращение для “on-board diagnostics” и относится к средствам само-диагностики и отчетности автомобиля. Протокол изначальное предназначен для ускорения процесса диагностики обслуживающим персоналом. Первые версии позволяли диагностировать некоторые проблемы в двигателе. Сейчас же в дополнении к возможностям диагностики добавляются и другие возможности такие как получение разной информации например о текущем расходе топлива, управление разными узлами например АКПП, режиме работы трансмиссии, получение координат GPS и другое. Узнать более детально как это работает и историю вы можете в Wikipedia.

Необходимые материалы


image
Прежде всего нам нужен OBDII адаптер способный работать с вашим автомобилем. Существует множество таких адаптеров. Некоторые из них имеют COM интерфейс, некоторые — USB интерфейс, а некоторые — Bluetooth интерфейс. Теоретически любой может быть использован для нашего приложения, но на практике лучшим вариантом все-же будет Bluetooth. Также адаптеры могут отличатся поддерживаемыми OBDII протоколами (т.е. фактически поддерживаемыми автомобилями). Так что если у вас под рукой есть автомобиль и подходящий OBDII адаптер, мы можем начать разработку нашего приложения.

Подождите — у вас действительно есть автомобиль достаточно близко к среде разработки? На самом деле мы могли бы использовать симулятор на первых порах. Один из вариантов, работающий у меня — это приложение OBDSim. Это открытый проект доступный для многих платформ. Но поскольку Bluetooth не поддерживается в Windows, то приложение нужно будет собрать из исходных кодов в Linux. Также обратите внимание, что скорее всего вам нужно будет внести изменения в исходный код для того чтоб изменить RFCOMM канал на первый доступный вместо предлагаемого канала 1.

Второй вариант — это аппаратный симулятор, который можно использовать вместо автомобиля. Я использовал ECUsim 2000 standard с включенным протоколом ISO 15765 (CAN). А OBDII адаптер я использовал ELM327 v.1.5
image

Разработка приложения



Давайте начнем с описания протокола, используемого для связи между Android устройством и OBDII адаптером/автомобилем. Это текстовый polling протокол. Это значит что все что вам нужно — это послать команду для того чтоб получить ответ. И знание какие команды можно посылать является ключевым.

Мы будем подключатся к адаптеру через Bluetooth. Похоже что Bluetooth Low Energy API был бы хорошим вариантом. Но поскольку он поддерживается всего несколькими устройствами, то сейчас слишком рано использовать его.

Протокол поддерживает некоторые AT комманды например выключение эха и управление возвратом каретки. Вторая часть протокола — это непосредственно протокол управления OBDII.

Общая схема работы приложения следующая:
  • подключится в OBDII адаптеру через Bluetooth
  • инициализировать OBDII адаптер с помощью AT комманд
  • непрерывно получать требуемые данные с автомобиля путем отправки соответствующих PID кодов


Подключение к OBDII адаптеру достаточно стандартное. Но одна вещь которую нужно сделать перед подключением — это выбор Bluetooth устройства. Отображение alert диалога со списком устройств вполне подойдет:

ArrayList<String> deviceStrs = new ArrayList<String>();
final ArrayList<String> devices = new ArrayList<String>();

BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = btAdapter.getBondedDevices();
if (pairedDevices.size() > 0)
{
    for (BluetoothDevice device : pairedDevices)
    {
        deviceStrs.add(device.getName() + "\n" + device.getAddress());
        devices.add(device.getAddress());
    }
}

// show list
final AlertDialog.Builder alertDialog = new AlertDialog.Builder(this);

ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.select_dialog_singlechoice,
        deviceStrs.toArray(new String[deviceStrs.size()]));

alertDialog.setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener()
{
    @Override
    public void onClick(DialogInterface dialog, int which)
    {
        dialog.dismiss();
        int position = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
        String deviceAddress = devices.get(position);
        // TODO save deviceAddress
    }
});

alertDialog.setTitle("Choose Bluetooth device");
alertDialog.show();


Не забудьте где нибудь сохранить адрес выбранного устройства. Теперь мы можем подключится к выбранному устройству:

BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
BluetoothDevice device = btAdapter.getRemoteDevice(deviceAddress);
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
BluetoothSocket socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
socket.connect();


UUID в коде выше представляет «последовательный» интерфейс через Bluetooth. Конечно этот код должен быть исполнен в не UI потоке. Также я бы рекомендовал посмотреть здесь за деталями и решением ошибки в Android которая может приводить к невозможности подключения в некоторых случаях.

Теперь мы можем обмениваться данными. Для этого мы будем использовать OBD-Java-API библиотеку. Библиотека достаточно простая. Она имеет несколько классов, которые соответствуют разным OBD командам. Не забудьте инициализировать OBDII адаптер путем посылки конфигурационных команд:
new EchoOffObdCommand().run(socket.getInputStream(), socket.getOutputStream());
new LineFeedOffObdCommand().run(socket.getInputStream(), socket.getOutputStream());
new TimeoutObdCommand().run(socket.getInputStream(), socket.getOutputStream());
new SelectProtocolObdCommand(ObdProtocols.AUTO).run(socket.getInputStream(), socket.getOutputStream());


Теперь мы готовы посылать другие команды:
EngineRPMObdCommand engineRpmCommand = new EngineRPMObdCommand();
SpeedObdCommand speedCommand = new SpeedObdCommand();
while (!Thread.currentThread().isInterrupted())
{
    engineRpmCommand.run(sock.getInputStream(), sock.getOutputStream());
    speedCommand.run(sock.getInputStream(), sock.getOutputStream());
    // TODO handle commands result
    Log.d(TAG, "RPM: " + engineRpmCommand.getFormattedResult());
    Log.d(TAG, "Speed: " + speedCommand.getFormattedResult());
}


image

Здесь я хочу отметить что библиотека имеет некоторые проблемы с парсингом и часто падает из-за недостаточно хорошей обработки ошибок. Первая проблема это метод performCalculations, который присутствует во всех классах команд. Было бы хорошо проверять размер буфера перед доступом к нему потому что в некоторых случаях ответ может быть короче чем нужно. Само собой проблема короткого ответа лежит на стороне OBDII адаптера/автомобиля, но библиотека должна быть готова к таким проблемам.

Кроме прочего там есть еще некоторые проблемы, так что эта библиотека все еще требует улучшений или просто может быть использована как источник информации.

Полученные данные могут быть сохранены где-нибудь для дальнейшего анализа, например в ElasticSearch.

А сейчас мы работаем над приложением Hours of Service для водителей грузовиков и продолжаем делится опытом в нашем блоге. Stay tuned!

P.S. На самом деле я также являюсь и автором оригинальной англоязычной версии статьи, которая была опубликована на blog.lemberg.co.uk, так что могу ответить на технические вопросы.
Share post

Comments 40

    +3
    Не дай боже Вам забыть этот датчик подключенным к авто на несколько дней без подзарядки аккумулятора. Уже дважды сажал аккумулятор в хлам этим эльмом.
      +3
      Странно… Обычно питание в OBD идёт по цепи зажигания, и на заглушенной машине адаптер не работает.
        +2
        Сильно зависит от машины.
        На некоторых Рено например, там еще и CAN разведен в колодке. И он не отключается.
          0
          Очевидно так обстоят дела у иномарок. В отечественных авто, питание идет и без зажигания. Тому пример, в отечественном авто регистратор работает без зажигания, на иномарке только при заведенном авто.
            +2
            Неочевидно. В разных машинах по-разному бывает и зачастую цепь гнезда прикуривателя не связана с цепью диагностического разъема. На первом Ford Focus при вытащенном ключе разъем не работает, но работает прикуриватель. У Рено Сандеро не работает ни то, ни другое…
            0
            У subaru forester питание на разъеме остаётся. Но неделю аккумулятор протянул. У bmv, насколько мне известно, аналогичная ситуация.
              0
              SH1 — модельный ряд 09 года — питание на разьеме уходит, если вытащить ключ.
              0
              питание к ELM идет по 16 ноге в разъеме. Пока ни разу не встречал, чтобы питание на этой ноге отключалось по выключению зажигания. Использовал на Aveo T250, T300, Toyota Rav4
                0
                Нет, поглядите распиновку разъёма. Там специально предусмотрен пин +12 v battery
                Он всегда подключен к АКБ.
                  0
                  Chrysler Neon II 2002г.в.
                  Лампочки на адаптере горят при выключеном зажигании…
                  +3
                  Проблема в другом.

                  Все эти адаптеры, по крайней мере которые есть у меня, не дают сменить стандартный пароль. А это значит, все кто хотят могут подключатся.
                    0
                    А в чем проблема, данные доступны только для чтения. Максимум сбросить ошибки могут, но тут только при заведенном авто.
                      +5
                      Ну мне сама идея, что читают все кому не лень, уже не нравится…
                        0
                        Пароль можно сменить выпаяв бт-модуль (обычно hc-05 или аналог) и по uart подать на него команду AT+PINxxxx

                        С помощью любительской проги на Ford Focus 2 можно очень много параметров настроить, а также прошить ЭБУ. Единственное но — без включенного зажигания это не сделаешь. Но медвежью услугу может оказать автозапуск
                      +1
                      Погуглил потребляемый ток данных девайсов. Пишут 20-40 мА. Чтобы таким током высадить 50 А/ч аккум нужно забыть датчик включенным на несколько месяцев.
                        +3
                        Не самый свежий 65 А•ч аккум высаживается за месяц 30 мА сигналки.
                        Если датчик еще включен постоянно, то время сокращается вдвое в лучшем случае.
                        А если учесть, что аккум может быть не самым свежим, и от его номинальных 65 А•ч осталось хотябы 30, то за неделю — легко.
                          +1
                          Значит или в аккуме не 65 А/ч, или в сигналке не 30мА. При таком токе 65 А/ч должен держать три месяца. Если, конечно, кроме сигналки нет больше потребителей.
                            0
                            А вы сможете высушить аккумулятор до 0 А•ч? (=
                              +2
                              Запросто.
                            0
                            Не самый свежий 65 А•ч аккум высаживается за месяц 30 мА сигналки.
                            Если датчик еще включен постоянно, то время сокращается вдвое в лучшем случае.
                            А если учесть, что аккум может быть не самым свежим, и от его номинальных 65 А•ч осталось хотябы 30, то за неделю — легко.

                            Согласен. Похожий модуль разрядил аккум моей машины за неделю
                            +1
                            Я тоже гуглил, удивлялся.
                            Но в наличии факт — трое суток с установленным датчиком — надо прикуриваться. Проверял оставляя на меньший срок, не доводя до предела — садит аккумулятор. Машине — неполных два года.
                            При выключении зажигания устройство из блутус пропадает.
                            Хотя не исключаю, что у меня бракованный экземпляр.
                              +1
                              Тут дело в другом. Датчиком-то можно высаживать аккумулятор несколько месяцев, но вот уже через пару недель аккумулятор не сможет выдать требуемый ток для прокручивания двигателя (а это больше сотни ампер).
                              +3
                              Датчик постоянно стоит на машине около года. Никаких проблем не было даже зимой. Пару раз в неделю на машине катаюсь конечно. Может за месяц без запуска двигателя и высадит аккумулятор.
                                0
                                солнечная панель на пару ватт легко решит эту проблему
                                  0
                                  В гараже? (=
                                    0
                                    если неоткрытый то таки облом
                                  0
                                  kia rio 2 стояла неделю. никаких проблем.
                                    0
                                    Это ж сколько он жрет? У меня сигналка за пару месяцев простоя не может посадить аккумулятор.
                                      0
                                      Я уже год пользуюсь ELM 327 (прямо как на картинке) в связке с eZWay. Проблема с аккумулятором действительно есть. Уехав в длительную командировку, не отключил адаптер (на тот момент попросту еще не знал об этом нюансе). Когда вернулся, пришлось заряжаться.
                                      0
                                      Очень познавательно, но зря завязли на bluetooth2.
                                      Он для этой задачи совсем не подходит.
                                      Если же взять c bluetooth4 то спящий режим решает проблему с аккумулятором( кроме того, что на порядок меньше потребляет, так еще есть спящий режим).
                                      А с паролем легко решается, производитель железки видать поленился.
                                      По bluetooth можно обновлять приложение и в том числе такие переменные как пароль.
                                      На этой неделе запускаем свой проект — там и софт и железка( правильная, которая от батарейки годами работает).
                                      Из не реализованных еще возможностей использование bluetooth4 для автооткрытия гаража и прочих радостей ibeacon.
                                      У bluegiga хорошие устройства, можно не зная си разрабатывать на BGScript.
                                      А, что б снизить потребление электричества в телефоне, в следующей версии gps перенесем в obd плагин.
                                        +1
                                        Все бы хорошо, только ряд производителей (PSA, GM) используют свои адаптеры с закрытым протоколом. «Cтандартный» OBD2 там тоже поддерживается, но не в полной мере. В частности, для Peugeot/Citroen будут доступны только коды ошибок ECU двигателя (к другим бортовым системам доступ только по CAN/VAN шинам) и текущие обороты двигателя.
                                          –1
                                          Эх, и тут ELM. Я, прочитав заголовок, подумал уж что OBDII реализовали…
                                            0
                                            Интересно а можно ли «газовать» через OBD (на авто педаль «электронная»)?
                                              0
                                              Через OBDII — точно нет. Это протокол диагностики, а не управления.
                                                0
                                                У меня висит на нем автодоводчик стекол. При нажатии на блокировку — поднимает открытые стекла. Так же при последовательном нажатии «открыть-закрыть-открыть» — открывает все 4 окна. Очень актуально летом, пока идешь к машине она чуток проветривается. При обратном нажатии — все ркна закрываются…
                                                  0
                                                  Значит это либо специфическое расширение от конкретного производителя, либо (скорее всего) — не OBDII, а CAN.
                                                  Вот CAN — как раз для управления используется очень широко. В новых машинах на нем много чего висит.
                                                    0
                                                    Как-то так…
                                                    image
                                                      0
                                                      Это интересно…
                                                      А как всё подключено? Доводчик штатный, и ему этот модуль дает команду? Если да — интересно, что за модуль такой…
                                                      Или же доводчик отдельно ставили, а модуль только «ловит» событие и дает напрямую команду доводчику?
                                                        0
                                                        Китайцы те еще умельцы.
                                                        Не знаю как все там устроено, на передних стеклах доводчик есть с завода. Т.е. как обычно нажал один раз стекло опустилось или поднялось само. На задних стеклоподъемниках доводчика нет. При блокировке со штатного ключа (не сторонняя сигналка, а встроенный центральный замок с пищалкой) — поднимает не закрытые окна. Шевроле Круз 12го года.
                                                        От мозгов зависит, полез на ebay, там в совместимости пишут
                                                        Applicable models: Cruze / Hideo / Buick / Mai Rui Bao / New Regal / LaCrosse / Ang Kela / New GL8 / Cadillac SRX
                                                        Еще есть для Фокуса.
                                                        И еще:
                                                        How it works:
                                                        CAN-BUS intelligent window up device uses advanced communication technologies, have passed the standard OBD Ⅱ diagnostic monitor door status, in order to implement a user-friendly design to automatic latch or window function, it does not affect the original vehicle bus communication system, to make up for the original car design defects, improve traffic safety and vehicles are more intelligent.
                                                          0
                                                          Ну т.е. как я и говорил. Используется CAN, просто он выведен на тот же разъем что и OBD II.
                                                          Тогда ничего необычного.

                                            Only users with full accounts can post comments. Log in, please.