Спецификация и описание функций J2534 ›
Спецификация и описание команд ELM327 ›
Интерфейс ELM327 доступен в адаптере Nano ET. Остальные адаптеры ScanDoc используют протокол J2534 PassThru.
Изменения в J2534 DLL, ELM327 и прошивках адаптеров ScanDoc, которые касаются интеграции: новые функции, протоколы и параметры - с примерами использования.
Скачать библиотеки J2534 2.0.0.213 - Windows x86/x64/ARM64 (отдельные сборки для Windows 7), macOS (universal), Linux (x64, x86, ARM, ARM64), Android (arm64-v8a, armeabi-v7a, x86, x86_64), iOS (XCFramework); в папке docs/ - документация SDK (начало работы, справочник API, конфигурация, обработка ошибок, DoIP, обновление прошивки, формат лога, Android, iOS). Статические .a поставляются только для iOS и серверной сборки Linux x64, остальные платформы загружают библиотеку динамически.
Исправлено
CAN_PS, ISO15765_PS, J1939_PS и установка выводов на каналах _PS - при подключении этих трёх протоколов прибор отвечал отказом; теперь они работают наравне с TP2_0_PS и ISO9141_PS. Установка выводов приведена к J2534-2 по трём пунктам:
PassThruConnect на выводах по умолчанию, хотя _PS-канал обязан молчать до SET_CONFIG(J1962_PINS). Теперь на шину канал выходит только после установки выводов.SET_CONFIG(J1962_PINS) переключал живой канал на другие контакты посреди сеанса. По стандарту выводы задаются на канал один раз: повторный вызов возвращает ERR_CHANNEL_IN_USE, другие выводы - только после PassThruDisconnect.ERR_PIN_NOT_SUPPORTED.uint32_t ch;
pt_config_t pins = { J1962_PINS, 0x0000060EU }; /* выводы 6 и 14 */
pt_config_list_t cfg = { 1, &pins };
PassThruConnect(dev, ISO15765_PS, 0, 500000, &ch);
/* канал ещё не на шине */
if (PassThruIoctl(ch, SET_CONFIG, &cfg, NULL) != STATUS_NOERROR) {
/* ERR_PIN_NOT_SUPPORTED - такого сочетания нет в разводке прибора */
}
/* только теперь PassThruWriteMsgs / PassThruReadMsgs;
повторный SET_CONFIG(J1962_PINS) - ERR_CHANNEL_IN_USE */
PassThruWriteMsgs возвращал успех, PassThruReadMsgs - пусто, а признак CONNECTION_LOST не выставлялся. Программирование ЭБУ по TP2.0 проверено на стенде.REQUEST_CONNECTION: десяток попыток к молчащему ЭБУ занимал все слоты фильтров и глушил канал; TEARDOWN_CONNECTION на TP1_6_PS отвечал отказом - закрыть соединение со стороны приложения было нельзя; TP2.0 не принимал соединение, установленное со стороны ЭБУ, и не отдавал приложению кадры, пришедшие вне соединения (§19.3.1 J2534-2).PassThruReadMsgs. Соединение здесь точка-точка, адрес тестера зарегистрирован при routing activation, отбирать нечего: канал отдаёт приложению все сообщения, PassThruStartMsgFilter отвечает ERR_NOT_SUPPORTED. Отказ в драйвере CAN перезагружал прибор посреди сеанса DoIP. Сторожевой таймер приёмной задачи поднят с 5 до 30 с - установление соединения DoIP штатно занимает до 20 с.PassThruConnect получал переполнение очереди на первом же сообщении. Базовые CAN и ISO15765 уходили на другой CAN-контроллер и не доходили до шины. Чтение приёмной очереди не восстанавливалось после испорченной записи - признак проверялся неверно во всех протоколах на базе CAN.GET_NDIS_ADAPTER_INFO - под кодом STATUS_NOERROR возвращались неинициализированные данные. Теперь приходят идентификатор адаптера, MAC, адрес IPv4, по которому прибор виден ЭБУ, и состояние линии активации; если Ethernet на приборе нет - ERR_NOT_SUPPORTED.GET_PROTOCOL_INFO - отвечал не за все протоколы и не тем форматом. Теперь работает на любом открытом канале: разрешение метки времени (1 мкс), поддерживаемая чётность, разрядность данных UART. Параметр, на который прибор ответить не может, помечается в поле supported, вызов при этом возвращает STATUS_NOERROR.PassThruDisconnect - обращение к уже завершившейся задаче канала портило память прибора.Новое
libj2534.xcframework содержит срезы для устройства (arm64) и симулятора (arm64/x86_64), минимальная версия iOS 12.0. В каждом срезе - заголовки j2534.h и j2534_ota.h, модульная карта (Swift import J2534, автолинковка CoreBluetooth) и privacy manifest. Прототипы Pass-Thru API объявлены в самом j2534.h - на всех платформах. mbedTLS вкомпилирован, внешних зависимостей нет. Подключение в Xcode: Embed = Do Not Embed (библиотека статическая), -lc++ в Other Linker Flags, ключи NSBluetoothAlwaysUsageDescription (BLE) и NSLocalNetworkUsageDescription (WLAN) в Info.plist - без них iOS завершает приложение при первом обращении к транспорту.
import J2534
var deviceId: UInt32 = 0
// PassThruOpen принимает mutable char* - передаём копию строки
var cstr = Array("ScanDoc;b:N4999".utf8CString) // BLE по префиксу имени
let ret = cstr.withUnsafeMutableBufferPointer { PassThruOpen($0.baseAddress, &deviceId) }
if ret == 0 {
var fw = [CChar](repeating: 0, count: 80)
var dll = [CChar](repeating: 0, count: 80)
var api = [CChar](repeating: 0, count: 80)
PassThruReadVersion(deviceId, &fw, &dll, &api)
PassThruClose(deviceId)
}
/* ID протоколов и IOCTL - макросы с приведением типа, в Swift не импортируются:
задавайте числом, let CAN: UInt32 = 5, let ISO15765: UInt32 = 6 */
ptOtaUpdate(devId, firmwarePath, callback) и ptOtaAbort(devId); ранее OtaUpdate/OtaAbort были доступны только через C API. Прогресс передаётся в onProgress(current, total) - блоки, нумерация с единицы.
// update.bin заранее скопирован в хранилище приложения.
// Вызов блокирующий - выполнять вне main thread.
val res = j2534.ptOtaUpdate(devId, file.absolutePath,
object : OtaProgressListener {
override fun onProgress(current: Int, total: Int) { /* прогресс-бар */ }
})
if (res.status == 0) {
// прошивка записана, прибор перезагружается: devId недействителен,
// подключение восстанавливается новым ptOpen (по BLE - ожидание ~10 с)
}
// res.status < 0 - код ota_result_t (см. j2534_ota.h)
// ptOtaAbort(devId) прерывает обновление без перезагрузки прибора
log_level в j2534.json: -1 выключено, 0 ошибки, 1 +предупреждения, 2 +info, 3 +debug, 4 +verbose; по умолчанию - 3, то есть без настройки лог пишется полностью. На уровне -1 папка sdlogs и файл .qlog не создаются, данные на диск не записываются. На Android уровень задаётся и из кода - ptSetLogLevel(int); заданный так уровень имеет приоритет над файлом конфигурации, поэтому в релизной сборке лог не может быть включён извне.
// Android: вызвать до ptOpen
j2534.ptSetLogLevel(-1) // релизная сборка - лог выключен
j2534.ptSetLogLevel(3) // обращение в поддержку - полный лог
// Остальные платформы: j2534.json в папке конфигурации
// macOS ~/Library/Application Support/Quantex/
// Linux ~/.config/quantex/
// Windows %APPDATA%\Quantex\
{ "log_level": -1, "devices": [] }
Исправлено
PassThruReadVersion и заголовок .qlog возвращали 2.0.0.0: номер сборки не передавался в сборку под Android. Версия определяется тем же правилом, что и на остальных платформах; этот номер указывается при обращении в поддержку.serial_*: USB-транспорт из iOS-сборки исключён, а вызовы к нему оставались. Транспорт заменён заглушкой - подключение строкой c: возвращает штатную ошибку открытия порта..qlog - данные сообщения записывались не далее 125 байт, а запись группы сообщений, переданных одним вызовом PassThruReadMsgs или PassThruWriteMsgs, ограничивалась фиксированным буфером. Сообщение и вся группа записываются полностью - это важно для длинных ответов, например списка DTC..qlog - библиотека и прибор формировали текст лога двумя независимыми реализациями, и расшифровка одних и тех же значений различалась. Флаг установленного соединения TP2.0 и TP1.6 в поле RxStatus библиотека печатала как CONNECTION_ESTABLISHED, прибор - как CONN_OK; имена IOCTL различались в 22 позициях. Теперь имена протоколов, флагов TxFlags и RxStatus, IOCTL и их параметров формируются единой реализацией, поэтому лог приложения и лог прибора по одному и тому же обмену читаются рядом.Скачать библиотеки J2534 2.0.0.200 - Windows x86/x64/ARM64 (отдельные сборки для Windows 7), macOS (universal), Linux (x64, x86, ARM, ARM64), Android (arm64-v8a, armeabi-v7a, x86, x86_64), iOS.
Новое
ISO13400_PS (0x8FFD) и HSFZ_PS (0x8FFC). В стандарт SAE J2534 они не входят - это собственное расширение ScanDoc: диагностика по Ethernet - обнаружение автомобилей в сети (VIN, логический адрес), TCP-подключение, routing activation, обмен UDS. Тестерный адрес по умолчанию 0 - задайте ISO13400_SOURCE_ADDR до активации маршрутизации, иначе шлюз ответит отказом; адрес ЭБУ передаётся в каждом сообщении ([TA][SA][UDS]), ISO13400_TARGET_ADDR через Set/GetConfig не задаётся. Отправка сериализуется по P2: один незакрытый UDS-запрос за раз, NRC 7F xx 78 продлевает ожидание до P2*max (6 с). Новый параметр канала ISO13400_P3_DOIP (0x8108) - пауза между сообщениями.
uint32_t ch, code = 0;
pt_config_t sa = { ISO13400_SOURCE_ADDR, 0x0E80 };
pt_config_list_t cfg = { 1, &sa };
PassThruConnect(dev, ISO13400_PS, 0, 0, &ch);
PassThruIoctl(ch, SET_CONFIG, &cfg, NULL); /* SA - до routing activation */
PassThruIoctl(ch, ISO13400_DISCOVER_VEHICLES, NULL, NULL); /* IP ЭБУ запомнится сам */
PassThruIoctl(ch, ISO13400_CONNECT_TCP, NULL, NULL);
PassThruIoctl(ch, ISO13400_ACTIVATE_ROUTING, NULL, &code); /* 0x10 = success */
/* дальше PassThruWriteMsgs / PassThruReadMsgs - обычный UDS */
0x55 (маркер кадра J2534) - J2534, любой другой (текстовая AT-команда) - ELM327.Исправлено
PassThruStartMsgFilter сравнивал только 4 байта CAN ID, игнорируя заданную длину фильтра. Теперь кадр сравнивается на всю длину, как требует стандарт: PASS/BLOCK по содержимому кадра работают.
/* Подавить ответы TesterPresent (07E8 02 7E ...) в приёмной очереди */
pt_msg_t mask = {0}, pattern = {0};
mask.protocol_id = pattern.protocol_id = CAN;
mask.data_size = pattern.data_size = 6; /* 4 байта CAN ID + 2 байта данных */
memcpy(mask.data, "\xFF\xFF\xFF\xFF\xFF\xFF", 6);
memcpy(pattern.data, "\x00\x00\x07\xE8\x02\x7E", 6);
uint32_t fid;
PassThruStartMsgFilter(ch, BLOCK_FILTER, &mask, &pattern, NULL, &fid);
AT SH при активном CAN-канале ломала Flow Control (FC уходил без паддинга, DLC=3 - шлюз не слал Consecutive Frames) и затирала приёмный фильтр своим TX ID (приём ответов без AT CRA ломался). По даташиту AT SH задаёт только заголовок передачи - приёмный фильтр теперь управляют только AT CRA/CF/CM.PassThruStopPeriodicMsg мог отправить лишний кадр после остановки._PS - выбор пинов через SET_CONFIG(J1962_PINS) не применялся, кадры не уходили на шину.Исправлено