hobdrive-docs

Спецификация формата ECUXML

ECUXML — это формат на основе XML, используемый в HOBDrive для описания параметров датчиков ЭБУ (электронного блока управления) автомобиля. Каждый файл .ecuxml определяет набор диагностических параметров OBD2/KWP2000 — как запрашивать данные у ЭБУ, как разбирать байты ответа и как отображать полученные значения пользователю.

Файлы ECUXML компилируются в классы-провайдеры датчиков на C# на этапе сборки с помощью утилиты ecuxml2cs либо загружаются динамически во время выполнения из внешних файлов.


Содержание


Структура файла

Корневой элемент: <parameters>

Каждый файл ECUXML имеет единственный корневой элемент <parameters>:

<?xml version="1.0" encoding="utf-8" ?>
<parameters namespace="MyECU"
            description="My ECU description"
            description-ru="Описание ЭБУ"
            standard-header="7E1">
  <!-- глобальные элементы и определения параметров -->
</parameters>

Атрибуты корневого элемента

Атрибут Обязательный Описание
namespace Нет Префикс пространства имён датчиков. Все идентификаторы параметров в этом файле будут иметь префикс Namespace., если идентификатор ещё не содержит точку. По умолчанию "Default".
description Нет Краткое описание профиля ЭБУ на английском. Отображается в интерфейсе выбора профиля.
description-ru Нет Краткое описание на русском.
standard-header Нет Заголовок ELM327 по умолчанию (ATSH), применяемый ко всем датчикам OBD2 в этом файле, если не переопределён для конкретного параметра.

Глобальные элементы

Эти дочерние элементы <parameters> настраивают профиль ЭБУ в целом. Они должны располагаться перед элементами <parameter>.

<include>

Включает другой файл ECUXML. Параметры из включённого файла загружаются в тот же реестр датчиков. Пути указываются относительно текущего файла.

<include>../kwp2000.ecuxml</include>
<include>IM-FAN.ecuxml</include>

Допускается несколько элементов <include>.

Строка заголовка ELM327 по умолчанию. Применяется ко всем датчикам OBD2, если не переопределена. Это альтернатива атрибуту standard-header на корневом элементе.

<header>7E1</header>

Может также содержать расширенные AT-команды, разделённые точкой с запятой:

<header>ATSH773; ATCRA774; ATFCSH773; 1092;</header>

<obd2-header>

Необязательный заголовок OBD2 по умолчанию. Если указан, это значение добавляется к строке инициализации ELM327. Также используется для восстановления заголовка по умолчанию после чтения датчика с пользовательским заголовком.

<obd2-header>7E0</obd2-header>

Или с расширенными командами:

<obd2-header>ATSH7E0; ATCRA7E8; ATFCSH7E0;</obd2-header>

<init-string>

Команды инициализации ELM327, разделённые точкой с запятой. Отправляются адаптеру при активации данного профиля ЭБУ.

<init-string>
  ATSP6; ATAL; ATSH7E0; ATST32;
</init-string>

<disable-obd2>

Определяет, загружаются ли стандартные датчики OBD2 вместе с пользовательскими датчиками этого файла.

<disable-obd2>false</disable-obd2>

При отключении доступны только датчики, определённые в этом файле ECUXML (и включённых файлах).

<models>

Список названий производителей автомобилей, разделённых запятыми или переводами строк. Используется для группировки в интерфейсе выбора ЭБУ.

<models>
  Mitsubishi
</models>
<models>Peugeot, Citroen</models>

<description lang="...">

Подробное описание профиля ЭБУ, отображаемое в интерфейсе. Атрибут lang задаёт язык ("en" или "ru").

<description lang="en">
  Extra OBD2 sensors for turbocharger diagnostics.
</description>
<description lang="ru">
  Дополнительные датчики OBD2 для диагностики турбокомпрессора.
</description>

Элемент параметра: <parameter>

Каждый <parameter> определяет один датчик. Атрибут id обязателен и служит идентификатором датчика в его пространстве имён.

<parameter id="CoolantTemp" display="PID05">
  <!-- дочерние элементы, описывающие датчик -->
</parameter>

Атрибуты параметра

Атрибут Описание
id Обязательный. Уникальный идентификатор датчика. Итоговый ID датчика будет Namespace.id, если id ещё не содержит точку.
display Необязательный отображаемый псевдоним. Используется в некоторых профилях ЭБУ как альтернативный код (например, Renault PR003, Toyota PID1).

Типы датчиков

Тип создаваемого датчика зависит от того, какие дочерние элементы присутствуют внутри <parameter>. Парсер проверяет их в определённом порядке приоритета:

1. Прямой датчик OBD2

Датчик, который напрямую запрашивает данные у ЭБУ командой (mode+PID или raw-команда) и разбирает байты ответа.

Создаётся когда: отсутствуют элементы <base>, <base-raw>, <base-data>, <class> или <text>.

<parameter id="CoolantTemp">
  <mode>1</mode>
  <command>05</command>
  <valuea>1</valuea>
  <offset>-40</offset>
  <description>
    <name>Coolant Temperature</name>
    <unit>celsius</unit>
  </description>
</parameter>

Или с использованием сокращения <address> (OBD2 Mode 1):

<parameter id="Lambda11" display="LAMBDA11">
  <address><byte>0x34</byte></address>
  <valueab>0.0000305</valueab>
</parameter>

Или с использованием сырой командной строки:

<parameter id="Core03">
  <raw>2103</raw>
  <valuea>0</valuea>
</parameter>

2. Производный датчик

Датчик, значение которого вычисляется на основе одного или двух других датчиков.

Создаётся когда: присутствует <base> и отсутствует <average>.

<parameter id="TC_CINP">
  <base>IntakeManifoldPressure</base>
  <valuea>0.01</valuea>
  <offset>0</offset>
  <description>
    <name>TC Pressure</name>
    <unit>bar</unit>
  </description>
</parameter>

С двумя базовыми датчиками и выражением eval:

<parameter id="CombinedValue">
  <base>SensorA</base>
  <base2>SensorB</base2>
  <eval>Sensor_Value * 2 + Sensor2_Value</eval>
</parameter>

Переменные, доступные в <eval> для производных датчиков:

3. Производный датчик Base-Raw

Датчик, который читает сырые байты ответа (включая все заголовки) другого датчика OBD2 и извлекает значение по определённому смещению.

Создаётся когда: присутствует <base-raw> и отсутствуют <text> / <dump>.

<parameter id="CVTdegr">
  <base-raw>Core10</base-raw>
  <word-31>1</word-31>
  <offset>0</offset>
</parameter>

Используется семейство методов getraw() — смещения являются абсолютными позициями в массиве сырых байтов (включая заголовки протокола).

Переменные, доступные в <eval> для датчиков base-raw:

4. Производный датчик Base-Data

Датчик, который читает байты данных другого датчика OBD2, пропуская стандартные заголовки протокола.

Создаётся когда: присутствует <base-data> (и отсутствуют <base> / <base-raw>).

<parameter id="TireSensor1">
  <base-data>Core_21A8</base-data>
  <eval>get(15)*0.2</eval>
  <description>
    <unit>psi</unit>
  </description>
</parameter>

Используется семейство методов get() — смещения отсчитываются от начала полезной нагрузки данных (после байтов mode+command).

Переменные, доступные в <eval> для датчиков base-data:

5. Текстовый датчик

Датчик, возвращающий текстовую строку из ответа ЭБУ, а не числовое значение (например, VIN-код, название ЭБУ).

Создаётся когда: присутствует элемент <text>.

Прямой текстовый датчик OBD2:

<parameter id="VIN">
  <mode>9</mode>
  <command>2</command>
  <text/>
</parameter>

Производный текстовый датчик из сырых данных:

<parameter id="ECUID_ECUIDT">
  <raw>1A80</raw>
  <text/>
</parameter>

Производный текстовый датчик из сырых данных другого датчика с eval:

<parameter id="StatusText">
  <base-data>CoreSensor</base-data>
  <text/>
  <eval>... выражение, возвращающее строку ...</eval>
</parameter>

Атрибуты <text>

Атрибут Описание
offset Смещение в байтах от начала ответа для начала чтения текста.
length Максимальное количество байтов для чтения.

6. Датчик дампа

Аналогичен текстовому датчику, но формирует шестнадцатеричный дамп сырых байтов. Полезен для диагностического отображения необработанных данных.

Создаётся когда: присутствует элемент <dump> с источником <base-data>.

<parameter id="ID_TireSensor_1">
  <base-data>TireSensorID</base-data>
  <dump offset="1" length="4"/>
</parameter>

Атрибуты <dump>

Атрибут Описание
offset Смещение в байтах от начала данных для начала дампа.
length Количество байтов для дампа.

7. Датчик среднего значения

Датчик, вычисляющий скользящее среднее значений другого датчика за указанное количество измерений.

Создаётся когда: присутствует элемент <average> вместе с <base>.

<parameter id="Avg_ECUFuelLevel">
  <base>ECUFuelInTank</base>
  <average length="15"/>
  <description>
    <unit>liters</unit>
  </description>
</parameter>

Атрибуты <average>

Атрибут Описание
length Количество значений для усреднения (размер окна интегрирования).

8. Датчик на основе класса

Датчик, реализованный именованным классом C#, а не логикой извлечения значений ECUXML.

Создаётся когда: присутствует элемент <class>.

<parameter id="MIL">
  <class>KWPMILSensor</class>
</parameter>
<parameter id="ClearDTC">
  <class>hobd.ClearDTCSensor</class>
</parameter>

Класс должен быть зарегистрирован в реестре датчиков и наследоваться от CoreSensor.


Извлечение значений

Спецификация команды

Существует три способа указать, какую команду отправить ЭБУ:

Mode + Command (стандартный OBD2)

<mode>1</mode>        <!-- Режим OBD2, в hex (напр., 1 = текущие данные) -->
<command>0C</command>  <!-- OBD2 PID, в hex -->

По умолчанию режим 1, если не указан.

Сокращение Address

Эквивалентно указанию mode 1 + заданный PID:

<address><byte>0x34</byte></address>

Сырая команда (Raw)

Шестнадцатеричная строка, отправляемая напрямую ELM327. Точки с запятой в строке преобразуются в символы возврата каретки (несколько команд). Переопределяет mode+command.

<raw>2103</raw>
<raw>14FF00</raw>
<raw>1A80</raw>

<header>

Переопределение заголовка для конкретного параметра. Изменяет заголовок ELM327 (ATSH) для запросов этого датчика, переопределяя как standard-header, так и глобальный <header>.

<parameter id="SpecialSensor">
  <header>7E1</header>
  <raw>2201</raw>
  <valuea>1</valuea>
</parameter>

<data-offset>

Переопределяет длину команды по умолчанию для разбора ответа. Обычно парсер пропускает CommandLength байтов (по умолчанию: 2, для Mode+Command) после нахождения маркера ответа. Этот элемент изменяет количество пропускаемых байтов.

<data-offset>2</data-offset>  <!-- пропустить 2 байта после маркера ответа -->
<data-offset>3</data-offset>  <!-- пропустить 3 байта (напр., для 3-байтных команд) -->

Однобайтовые значения

Извлечение одного байта из данных ответа с умножением на масштабирующий коэффициент.

Элемент Смещение Описание
<value> или <valuea> 0 Первый байт данных (байт A)
<valueb> 1 Второй байт данных (байт B)
<valuec> 2 Третий байт данных (байт C)
<valued> 3 Четвёртый байт данных (байт D)
<value-N> N Байт по смещению N

Содержимое элемента — это масштабирующий коэффициент (множитель):

<valuea>0.392157</valuea>   <!-- результат = байт_A * 0.392157 -->
<valueb>1</valueb>           <!-- результат = байт_B * 1 -->
<value-6>1</value-6>         <!-- результат = байт_по_смещению_6 * 1 -->

Значения Word (16 бит)

Извлечение 16-битного слова big-endian (два последовательных байта) с умножением на масштаб.

Элемент Смещение Описание
<valueab> 0 Слово из байтов A, B (смещения 0, 1)
<valuebc> 1 Слово из байтов B, C (смещения 1, 2)
<valuecd> 2 Слово из байтов C, D (смещения 2, 3)
<word-N> N Слово начиная со смещения N
<valueab>0.0000305</valueab>  <!-- результат = word(A,B) * 0.0000305 -->
<word-31>1</word-31>           <!-- результат = слово по смещению 31 -->

Значения DWord (32 бита)

Извлечение 32-битного двойного слова big-endian (четыре последовательных байта) с умножением на масштаб.

Элемент Смещение Описание
<dword-N> N Двойное слово начиная со смещения N
<dword-0>0.001</dword-0>  <!-- результат = dword по смещению 0 * 0.001 -->

Варианты Little-Endian

Для ЭБУ, передающих данные в порядке байтов little-endian:

Элемент Описание
<wordle-N> 16-битное слово little-endian по смещению N
<dwordle-N> 32-битное двойное слово little-endian по смещению N
<wordle-8>0.0018252</wordle-8>  <!-- LE-слово по смещению 8 -->

Конвейер преобразования значений

После извлечения исходного числового значения применяются следующие преобразования в указанном порядке:

1. Преобразование в знаковое (<signed/>)

Если присутствует, извлечённое значение переинтерпретируется как знаковое целое:

<signed/>

2. Масштаб и смещение

результат = исходное_значение * масштаб + смещение

Где масштаб берётся из содержимого элемента значения, а смещение — из элемента <offset>.

<valuea>1</valuea>
<offset>-40</offset>   <!-- напр., температура ОЖ: байт_A * 1 + (-40) -->

3. Извлечение бита (<bit> и <bit-width>)

Если указан <bit>, результат сдвигается вправо на заданное количество бит, затем маскируется для извлечения <bit-width> бит (по умолчанию: 1).

<bit>10</bit>          <!-- извлечь бит 10 -->
<bit-width>3</bit-width> <!-- извлечь 3 бита -->

Формула: результат = (int(масштабированное_значение) >> bit) & ((1 << bit_width) - 1)

Часто используется для извлечения булевых флагов или небольших полей из байтов состояния:

<parameter id="FuelSystemStatus_Trim">
  <base>FuelSystemStatus</base>
  <value>1</value>
  <bit>10</bit>
</parameter>

4. Фильтры отсечения (<cut-low> и <cut-high>)

Обнуление недопустимых/зашумлённых значений:

<cut-low>500</cut-low>    <!-- значения ниже 500 становятся 0 -->
<cut-high>220</cut-high>   <!-- значения выше 220 становятся 0 -->

Полезно для фильтрации ошибок ЭБУ (например, фантомные показания оборотов при выключенном двигателе):

<parameter id="RPM">
  <base>RPM</base>
  <value>1</value>
  <cut-low>500</cut-low>
</parameter>

Группа MIL (<mil-group>)

Для датчиков MIL (индикатор неисправности) указывает, к какой группе диагностических кодов неисправностей относится данный датчик:

<mil-group>TPMS_Suzuki</mil-group>
<mil-group>HyundaiSRS</mil-group>

Динамические выражения (<eval>)

Элемент <eval> содержит динамическое выражение, вычисляющее значение датчика. При наличии переопределяет стандартный конвейер извлечения значений (масштаб/смещение).

<eval>get(13)*0.2</eval>
<eval>(0.000000002344*(get(13)^5))+(-0.000001387*(get(13)^4))+(0.0003193*(get(13)^3))+(-0.03501*(get(13)^2))+(2.302*get(13))+(-36.6)</eval>
<eval>get(6)*65536+get(7)*256+get(8)</eval>
<eval>Sensor_Value * 2 + Sensor2_Value</eval>

Синтаксис выражений

Вычислитель выражений основан на движке формул, подобном Excel. Поддерживаются:

Приоритет операторов (от высшего к низшему)

Приоритет Операторы Описание
1 ( ), f(x) Группировка, вызовы функций
2 !, ~, -, + Унарные операторы
3 ^ Степень (левоассоциативная: a^b^c = (a^b)^c)
4 *, /, % Умножение, деление, остаток
5 +, - Сложение, вычитание
6 & Конкатенация строк
7 <, <=, >, >= Сравнение
8 =, !=, <> Равенство
9 && Логическое И
10 \|\| Логическое ИЛИ
11 ?: Тернарный условный оператор
12 := Присваивание

Типы данных

Поддерживается пять типов данных: double, int, hexadecimal, string и boolean.

Целые числа и шестнадцатеричные значения автоматически преобразуются в double при вычислениях. Для явного преобразования используйте int().

Встроенные функции

Движок выражений поддерживает следующие стандартные функции:

Abs, Acos, And, Asin, Atan, Atan2, Avg, Ceiling, Cos, Cosh, Exp, Fact, Floor, Format, Hex, If, Left, Len, Ln, Log, Lower, Max, Min, Mid, Not, Or, Pow, Right, Round, Sign, Sin, Sinh, Sqr, Sqrt, StDev, Trunc, Upper, Val, Var

If(условие; значение_истина; значение_ложь)

Условная функция. Эквивалентна условие ? значение_истина : значение_ложь.

Примечание: аргументы функции разделяются точкой с запятой (;), а не запятыми.

Функции, специфичные для ECUXML

Эти функции доступны только в выражениях <eval> в определениях параметров ECUXML. Они работают с буфером сырых данных текущего датчика.

get(offset)

Возвращает один байт из буфера данных датчика по заданному смещению. Смещение отсчитывается от начала полезной нагрузки данных (после пропуска маркера ответа и байтов команды).

<eval>get(0)</eval>          <!-- первый байт данных -->
<eval>get(13)*0.2</eval>     <!-- байт по смещению 13 с масштабированием -->

get_word(offset)

Возвращает 16-битное слово big-endian (два байта), начиная с заданного смещения.

<eval>get_word(8)*0.1</eval>
<eval>get_word(2)*0.005+2.1</eval>

get_dword(offset)

Возвращает 32-битное двойное слово big-endian (четыре байта), начиная с заданного смещения.

<eval>get_dword(0)*0.001</eval>

get_wordle(offset)

Возвращает 16-битное слово little-endian, начиная с заданного смещения.

<eval>get_wordle(0)*0.3144</eval>

get_dwordle(offset)

Возвращает 32-битное двойное слово little-endian, начиная с заданного смещения.

<eval>get_dwordle(0)</eval>

to_signed_byte(value) / to_signed(value)

Преобразует байтовое значение (0–255) в знаковый байт (от -128 до 127).

<eval>to_signed_byte(get(5))*0.5</eval>

to_signed_word(value)

Преобразует 16-битное беззнаковое значение в знаковое 16-битное целое (от -32768 до 32767).

<eval>to_signed_word(get_word(0))*0.1</eval>

to_signed_dword(value)

Преобразует 32-битное беззнаковое значение в знаковое 32-битное целое.

Контекстные переменные eval

В зависимости от типа датчика, в выражениях eval доступны различные переменные:

Тип датчика Доступные переменные
Прямой OBD2 (<raw> или <mode>/<command>) Sensor — объект датчика OBD2 (используйте get(), get_word() и др.)
Производный (<base>) Sensor_Value — значение double базового датчика; Sensor2_Value — значение датчика <base2>
Base-raw (<base-raw>) Sensor — объект базового датчика OBD2
Base-data (<base-data>) Sensor — объект базового датчика OBD2

Описание и локализация

Каждый параметр может иметь один или несколько блоков <description> для локализации.

<parameter id="CVTTemp">
  <description>
    <name>CVT Temperature</name>
    <description>CVT oil temperature</description>
    <unit>celsius</unit>
    <display>CVTTEMP</display>
  </description>
  <description lang="ru">
    <name>Темп. CVT</name>
    <description>Температура масла вариатора</description>
    <unit>celsius</unit>
  </description>
</parameter>

Атрибуты <description>

Атрибут Описание
lang Код языка ("en", "ru" и др.). Если не указан, по умолчанию "" (по умолчанию/английский).

Дочерние элементы <description>

Элемент Описание
<name> Человекочитаемое имя датчика. Отображается в интерфейсе.
<description> Развёрнутое описание / текст подсказки.
<unit> Строка единицы измерения (например, celsius, bar, psi, km, volts, liters, rpm, cm). HOBDrive использует её для конвертации единиц.
<display> Переопределение формата отображения.

Полные примеры

Пример 1: Простой датчик OBD2 с Mode/Command

Стандартная температура охлаждающей жидкости OBD2 (PID 0x05):

<parameter id="CoolantTemp">
  <address><byte>0x05</byte></address>
  <valuea>1</valuea>
  <offset>-40</offset>
  <description>
    <name>Coolant Temperature</name>
    <unit>celsius</unit>
  </description>
</parameter>

Формула вычисления: байт_A * 1 + (-40) → температура в °C.

Пример 2: Производный датчик с фильтром отсечения

Фильтрация зашумлённых значений оборотов:

<parameter id="RPM">
  <base>RPM</base>
  <value>1</value>
  <cut-low>500</cut-low>
</parameter>

Берёт существующее значение датчика оборотов, пропускает без изменений (масштаб=1), но возвращает 0, если ниже 500.

Пример 3: Base-Data с выражением Eval

Давление TPMS из многобайтового ответа:

<parameter id="TireSensor1">
  <description>
    <unit>psi</unit>
  </description>
  <base-data>Core_21A8</base-data>
  <eval>get(15)*0.2</eval>
</parameter>

Читает байт по смещению 15 из полезной нагрузки Core_21A8, умножает на 0.2.

Пример 4: Полиномиальное выражение Eval

Преобразование температуры масла CVT с помощью аппроксимирующего полинома:

<parameter id="CVTTemp">
  <description lang="ru">
    <name>Темп. CVT</name>
    <unit>celsius</unit>
  </description>
  <base-data>Core03</base-data>
  <eval>(0.000000002344*(get(13)^5))+(-0.000001387*(get(13)^4))+(0.0003193*(get(13)^3))+(-0.03501*(get(13)^2))+(2.302*get(13))+(-36.6)</eval>
</parameter>

Пример 5: Сырая команда с текстовым ответом

Чтение идентификационного номера транспортного средства (VIN):

<parameter id="VIN">
  <description>
    <name>VIN Code</name>
    <description>Vehicle's VIN code</description>
  </description>
  <mode>9</mode>
  <command>2</command>
  <text/>
</parameter>

Пример 6: Датчик шестнадцатеричного дампа

Отображение идентификаторов датчиков давления в шинах:

<parameter id="ID_TireSensor_1">
  <base-data>TireSensorID</base-data>
  <dump offset="1" length="4"/>
</parameter>

Пример 7: Сырая команда KWP2000 с текстом

<parameter id="VIN">
  <raw>1A90</raw>
  <text/>
</parameter>

Пример 8: Знаковое значение Word в формате Little-Endian

<parameter id="SteeringAngle">
  <base-data>CoreSensor</base-data>
  <wordle-8>0.0018252</wordle-8>
  <signed/>
</parameter>

Пример 9: Датчик MIL на основе класса

<parameter id="MIL">
  <class>KWPMILSensor</class>
  <raw>1800FF00</raw>
  <mil-group>HyundaiSRS</mil-group>
</parameter>

Пример 10: Датчик среднего значения

<parameter id="Avg_ECUFuelLevel">
  <description lang="ru">
    <name>Уровень топлива (ЭБУ, сред.)</name>
    <unit>liters</unit>
  </description>
  <base>ECUFuelInTank</base>
  <average length="15"/>
</parameter>

Пример 11: Файл с включениями и глобальной конфигурацией

<?xml version="1.0" encoding="utf-8" ?>
<parameters namespace='Mitsubishi_4N15'
            description="Mitsubishi 4N15+AT_V8AWG+TPMS+OBD">
  <disable-obd2>false</disable-obd2>
  <obd2-header>ATSH7E0; ATCRA7E8; ATFCSH7E0;</obd2-header>
  <header>ATSH7E0; ATCRA7E8; ATFCSH7E0;</header>
  <init-string>
    ATSP6; ATST32; ATAT0; ATSH7E0; ATCRA7E8; ATFCSH7E0; ATFCSD300040; ATFCSM1;
  </init-string>
  <models>Mitsubishi</models>

  <include>mitsubishi_eng_4n15.ecuxml</include>
  <include>mitsubishi_at_v8awg.ecuxml</include>
  <include>mitsubishi_ks_tpms.ecuxml</include>

  <!-- Дополнительные параметры для этой комбинации -->
</parameters>

Организация файлов

Файлы ECUXML в проекте HOBDrive организованы по производителям автомобилей:

ecu/
├── obd2.ecuxml              # Стандартные дополнительные датчики OBD2
├── kwp2000.ecuxml           # Общие датчики протокола KWP2000
├── _cuts.ecuxml             # Патч: фильтрация зашумлённых значений датчиков
├── _gpsspeed.ecuxml         # Патч: использование скорости GPS вместо ЭБУ
├── _micas_obd2.ecuxml       # Патч: топливная коррекция для ЭБУ Micas
├── _vaz_obd2.ecuxml         # Патч: топливная коррекция для автомобилей ВАЗ
├── _toyotajdmclear.ecuxml   # Патч: логика сброса MIL для JDM
├── China/                   # Китайские автомобили (Chery, Geely, Haval и др.)
├── ChryslerDodgeJeep/
├── CitroenPeugeot/
├── FiatLanciaAlfaRomeo/
├── FordMazda/
├── GM/
├── HyundaiKIA/
├── Mercedes/
├── Mitsubishi/
├── Nissan/
├── Opel/
├── Renault/
├── SsangYong/
├── Subaru/
├── Suzuki/
├── Toyota/
├── VAG/
└── VAZ_GAZ_UAZ_ZAZ/

Файлы с префиксом подчёркивания (_*.ecuxml) — это «патч»-файлы, которые модифицируют или переопределяют существующие датчики.


Конвейер сборки

Файлы ECUXML обрабатываются утилитой сборки ecuxml2cs:

  1. Разбор: Все файлы .ecuxml разбираются парсером ECUXMLParser в объекты ECUXMLRootElement.
  2. Генерация провайдеров датчиков: Каждый файл ECUXML генерирует класс C# (через T4-шаблон EcuXmlTemplate.tt), наследующий BaseECUXMLSensorProvider. Сгенерированный класс содержит предварительно разобранные определения параметров в виде объектов ECUXMLParameterElement.
  3. Генерация реестра: ECUXMLSensorProviderRegistry.cs — связывает имена файлов .ecuxml с соответствующими сгенерированными классами провайдеров датчиков.
  4. Генерация реестра описаний: ECUXMLDescriptionRegistry.cs — хранит метаданные профилей ЭБУ (название, строка инициализации, модели) для профилей, у которых определён элемент <models>.
  5. Генерация списка ЭБУ: Markdown-файл со списком всех доступных профилей ЭБУ.

Во время выполнения ECUXMLSensorProvider сначала проверяет скомпилированный реестр на совпадение имени файла; если совпадение не найдено, выполняется разбор файла ECUXML напрямую с диска через FilesECUXMLSensorProvider.


Краткий справочник: все дочерние элементы параметра

Элемент Описание
<class> Имя класса C#, реализующего этот датчик
<mode> Режим OBD2 (hex), по умолчанию: 1
<command> OBD2 PID (hex)
<address><byte>0xNN</byte></address> Сокращение для mode 1 + PID NN
<raw> Сырая hex-строка команды (точки с запятой → CR)
<header> Переопределение заголовка ELM327 для датчика
<data-offset> Переопределение длины команды для ответа
<base> Ссылка на базовый датчик (производный)
<base2> Ссылка на второй базовый датчик (производный)
<base-raw> Ссылка на базовый датчик (доступ к сырым байтам)
<base-data> Ссылка на базовый датчик (доступ к байтам данных)
<value> / <valuea> Масштабирующий коэффициент, байт по смещению 0
<valueb> Масштабирующий коэффициент, байт по смещению 1
<valuec> Масштабирующий коэффициент, байт по смещению 2
<valued> Масштабирующий коэффициент, байт по смещению 3
<value-N> Масштабирующий коэффициент, байт по смещению N
<valueab> Масштабирующий коэффициент, big-endian word по смещению 0
<valuebc> Масштабирующий коэффициент, big-endian word по смещению 1
<valuecd> Масштабирующий коэффициент, big-endian word по смещению 2
<word-N> Масштабирующий коэффициент, big-endian word по смещению N
<wordle-N> Масштабирующий коэффициент, little-endian word по смещению N
<dword-N> Масштабирующий коэффициент, big-endian dword по смещению N
<dwordle-N> Масштабирующий коэффициент, little-endian dword по смещению N
<signed/> Интерпретировать значение как знаковое целое
<offset> Аддитивное смещение, применяемое после масштабирования
<bit> Величина сдвига вправо для извлечения бита
<bit-width> Количество извлекаемых бит (по умолчанию: 1)
<cut-low> Обнуление результата, если ниже порога
<cut-high> Обнуление результата, если выше порога
<eval> Динамическое выражение (переопределяет масштаб/смещение)
<text/> Пометить как текстовый датчик
<dump/> Пометить как датчик hex-дампа
<average/> Пометить как датчик усреднения
<mil-group> Идентификатор группы MIL/DTC
<description> Локализованное имя, описание, единица измерения