Вышедшая несколько лет назад пятая версия программы VCP System дала возможность всем, кто использует этот инструмент для кодирования автомобилей концерна VAG, значительно упростить, а самое главное ускорить, выполнение многих рутинных процедур. Конечно, возможности встроенного редактора и доступные методы взаимодействия с пользователем несколько далеки от современных трендов, однако, в большинстве случаев предоставленных возможностей более чем достаточно, ведь, если не большинство, то очень много операций можно свести к банальному выбору из двух: да или нет.
Эта первая заметка в серии, прямо и косвенно посвященных VCP Scripter, и она представляет собой перевод описания функций и процедур, пересисленных в официальном API (доступен на официальном сайте по по этой ссылке) на русский язык с минимальным количеством комментариев с моей стороны.
Итак, давайте посмотрим что нам предлагается в API VCP Scripter актуальной, на момент публикации этой заметки, восьмой версии программы VCP System.
Взаимодействие с пользователем
Вариантов взаимодействия с пользователем очень немного, прямо скажем: в нашем распоряжении всего одна процедура для вывода Writeln() и одна функция AskUserForInput() для ввода.
procedure Writeln(s: string);
Процедура позволяет выводить значение строковой переменной s в окно сообщений. Фактически это единственный вариант оперативного вывода информации в окно пользователя.
function AskUserForInput(const Prompt: string) : string;
Функция строит диалоговое окно с полем ввода. Результат ввода возвращается в виде строки.
Взаимодействие с блоками
В этом разделе доступных функций и процедур намного больше. Можно работать как со старыми блоками, использующими протокол KWP2000, так и с новыми, использующими протокол UDS. Конечно, в Scripter представлены не все команды поддерживаемых протоколов, а лишь очень небольшая часть, иногда это даже упрощенная реализация соответствующих команд, но, с другой стороны, вряд ли нужно бОльшее для создания скриптов, выполняющих типовые задачи по смене кодирования в блоках.
function IsConnectedToEcu : boolean;
Функция возвращает текущее состояние подключения к блоку. В случае успешного подключения к блоку функция возвращает TRUE, в противном случае FALSE.
procedure CloseCommunication;
Процедура закрывает соединение с блоком.
function ConnectToEcuTP20(aw : string) : boolean;
Функция выполняет подключение к блоку с адресом aw, переданному в виде строки, по протоколу TP2.0. В случае успешного подключения к блоку функция возвращает TRUE, в противном случае FALSE.
function ConnectToEcuUDS(aw : string) : boolean;
Функция выполняет подключение к блоку с адресом aw, переданному в виде строки, по протоколу UDS. В случае успешного подключения к блоку функция возвращает TRUE, в противном случае FALSE.
function ConnectToEcuTP16(aw : string) : boolean;
Функция выполняет подключение к блоку с адресом aw, переданному в виде строки, по протоколу TP1.6. В случае успешного подключения к блоку функция возвращает TRUE, в противном случае FALSE.
function ConnectToEcuKLine(aw : string) : boolean;
Функция выполняет подключение к блоку с адресом aw, переданному в виде строки, по протоколу KWP2000/KWP1281. В случае успешного подключения к блоку функция возвращает TRUE, в противном случае FALSE.
function DoLogin(login : integer) : boolean;
Функция вызывает процедуру авторизации в блоке используя в качестве параметра значение login, переданное в виде integer. В случае успешного подключения к блоку функция возвращает TRUE, в противном случае FALSE.
function DoReadAPK(channel : integer) :string;
Функция читает значение канала адаптации номер channel, переданного в виде строки. Функция возвращает пустую строку, если в процессе чтения канала произошла ошибка.
function DoWriteAPK(channel : integer ; value : string) : boolean;
Функция записывает значение value, переданное в виде строки, в канал номер channel, переданный в виде integer. В случае успешной записи функция возвращает TRUE, в противном случае FALSE.
function ChangeDiagSession(session : integer) : boolean;
Функция позволяет сменить тип диагностической сессии на standard (0), engineer (1) или EndOfLine (2) путем передачи соответствующего значения в параметре session типа integer. В случае успешной смены сессии функция возвращает TRUE, в противном случае FALSE.
function ReadDataByID(ID : integer) : string;
Функция читает значение параметра по указанному адресу ID, который передается переменной типа integer. При работе с функцией важно помнить несколько моментов. Первый заключается в том, что в соответствии с протоколом UDS адрес параметра это два байта, т.е. доступный диапазон адресов это 0-0xFFFF (HEX) или 0-65535 (DEC). Второй момент связан с тем, что диапазон 0-65535 поделен на поддиапазоны, в которых находятся определенные функциональные группы (например, каналы адаптаций и измеряемые величины), поэтому используя одну и туже функцию мы можем читать и каналы адаптации, и значение измеряемых величин, и целый ряд других параметров. Наконец, третий момент связан с тем, что длина строки, возвращаемой этой функцией зависит от читаемого параметра и будет меняться в зависимости от того, что вы читаете.
function WriteDataByID(ID : integer ; DataToWrite : string) : Boolean;
Функция записывает значение DataToWrite, переданного в виде строки, по указанному адресу ID. В случае успешной записи функция возвращает TRUE, в противном случае FALSE.
function WriteDataByIDRaw(ID : integer ; DataToWrite : string) : Boolean;
Функция аналогична функции WriteDataByID(), отличие заключается в том, что эта функция не передает в блок “отпечаток” тестера, изменившего параметр.
function ReadLongCoding : string
Функция читает значение длинного кодирования. Функция возвращает пустую строку, если в процессе чтения произошла ошибка.
function WriteLongCoding(codestring : string) : Boolean
Функция записывает значение длинного кодирования codestring, переданного в виде строки. В случае успешной записи функция возвращает TRUE, в противном случае FALSE.
function WriteShortCoding(coding : integer) : Boolean
Функция записывает значение короткого кодирования coding, переданного в виде строки. В случае успешной записи функция возвращает TRUE, в противном случае FALSE.
procedure ClearDTC;
Процедура удаляет все ошибки в блоке, с которым установлено соединение.
function ReadMemory(addr,amount_to_read : integer ; alfid : integer) : string;
Функция читает amount_to_read байт по адресу addr, используя значение ALFID равным alfid. Все параметры передаются в виде переменных типа integer. Результат чтения возвращается в виде строки, длина которой пропорциональна количеству запрашиваемых для чтения байт. Что касается параметра ALFID, то это сокращенное название одного из параметра соответствующей команды протокола UDS. Уверен, многие из вас встречали этот параметр при подготовке датасетов или загрузке контейнеров в VCP. Полностью название этого параметра звучит как Address and Length Format ID, что можно перевести как идентификатор формата адреса и длины. Размер ALFID всегда 1 байт. В API приводится его “стандартное” значение равное 0x44. Для протоколов отличных от UDS “стандартное” значение 0x00. К сожалению, Scripter предлагает сильно упрощенный вариант относительно возможностей, доступных в самом VCP и заложенных оригинальными протоколами, поэтому за один вызов функции мы можем прочитать не более 8 байт. Если нужно прочитать больше, вызывайте функцию еще раз.
function WriteMemory(addr: integer ; DataToWrite : string ; alfid : integer) : Boolean;
Функция осуществляет запись от 1 до 8 байт, переданных в виде строки DataToWrite, по адресу addr, переданному в виде integer, используя параметр ALFID, равным alfid, переданному в виде integer. В случае успешной записи функция возвращает TRUE, в противном случае FALSE.
function ReadMemoryByAddr(addr,amount_to_read : integer ; alfid : integer) : string;
Функция аналогична функции ReadMemory(), но использует режим прямого чтения. В случае успешной записи функция возвращает TRUE, в противном случае FALSE.
function WriteMemoryByAddr(addr: integer ; DataToWrite : string ; alfid : integer) : Boolean;
Функция аналогична функции WriteMemory(), но использует режим прямой записи. В случае успешной записи функция возвращает TRUE, в противном случае FALSE.
function GetECUShortCoding : string
Функция читает значение короткого кодирования. Функция возвращает пустую строку, если в процессе чтения произошла ошибка.
Procedure SendRawUDSData(RawUDSCommand : string)
Процедура позволяет отправить команду UDS протокола напрямую в блок. Я сомневаюсь, что данная процедура будет востребована, с учетом того, что UDS это закрытый протокол. Небольшой комментарий к примеру, приведенному в API для 310103D3040000:
- 0x31 – код команды UDS: RoutineControl – управление подпрограммами;
- 0x01 – тип RoutineControl: StartRoutine – запуск подпрограммы;
- 0х03D3 – идентификатор подпрограммы;
- 0x040000 – опциональный параметр подпрограммы.
function GetECUODXVersion : string
Функция возвращает значение версии контейнера ODX из блока в виде строки. Функция возвращает пустую строку, если в процессе чтения произошла ошибка.
function GetECUODXId : string
Функция возвращает значение ID ODX контейнера в виде строки. Функция возвращает пустую строку, если в процессе чтения произошла ошибка.
function GetECUSWVersionHEX : string
Функция возвращает значение версии ПО блока в виде строки. Функция возвращает пустую строку, если в процессе чтения произошла ошибка.
function GetECUDescription : string
Функция возвращает значение описания блока в виде строки. Функция возвращает пустую строку, если в процессе чтения произошла ошибка.
function GetECUNo : string
Функция возвращает значение партномера блока в виде строки. Функция возвращает пустую строку, если в процессе чтения произошла ошибка.
Функции для работы со строковыми представлениями байтовых массивов
В ранних версиях API некоторые из этих функций отсутствовали и пользователям приходилось писать собственные реализации. Как вы уже могли заметить, Scripter ориентирован на работу со строковыми переменными, при этом изначально все протоколы бинарные. Функции перечисленные ниже позволяют с легкостью менять значения в строковых переменных, являющихся строковыми представлениями байтовых массивов.
function SetBitInHexString(HexString : string ; ByteNo,BitNo : integer) : string;
Функция устанавливает значение бита номер BitNo равным 1 в байте номер ByteNo в строке HexString, представляющей собой последовательность байтов, и возвращает результат в виде новой строки. Байты считаются слева-направо. Нумерация байтов начинается с 1. Нумерация битов начинается с 0.
function ClearBitInHexString(HexString : string ; ByteNo,BitNo : integer) : string;
Функция устанавливает значение бита номер BitNo равным 0 в байте номер ByteNo в строке HexString, представляющей собой последовательность байтов, и возвращает результат в виде новой строки. Байты считаются слева-направо. Нумерация байтов начинается с 1. Нумерация битов начинается с 0.
function TestBitInHexString(HexString : string ; ByteNo,BitNo : integer) : boolean ;
Функция проверяет значение бита номер BitNo в байте номер ByteNo в строке HexString, представляющей собой последовательность байтов, и возвращает TRUE в случае, если бит установлен в 1, и FALSE в случае, если бит равен 0. Нумерация байтов начинается с 1. Нумерация битов начинается с 0.
function ChangeBytesInHexString(HexString,NewBytes : string ; ByteNo : integer) : string;
Функция заменяет фрагмент в строке HexString, представляющей собой последовательность байтов, новым фрагментом NewBytes, начиная с позиции ByteNo, и возвращает результат в виде новой строки. Нумерация байтов начинается с 1.
function IntToBCD(input,digits : integer) : string ;
Функция возвращает результат преобразования числа input в двочино-десятичный код (BCD) в виде строки. В случае, если длина кода окажется меньше чем digits строка будет автоматически выровнена 0 по левому краю.
Вспомогательные функции
Как следует из заголовка, данные функции могут быть полезными при реализации определенных сценариев в скрипте, например, определении модели автомобиля, логирования действий скрипта в файл и т.п.
function GetApplicationPath : string ;
Возвращает путь к папке, в которой установлена программа VCP, в виде строки.
function GetCurrentScriptPath : string ;
Возвращает путь папке из которой был запущен скрипт в виде строки.
function GetCardSerial : string ;
Функция возвращает серийный номер адаптера VCP в виде строки.
function ReadVIN : string ;
Функция VIN автомобиля, прочитанный из ЭБУ двигателя, в виде строки.
procedure SaveStringToFile(stringtosave,filename : string) ;
Процедура осуществляет запись строки stringtosave в файл, полный путь к которому передаётся в виде строки filename. При вызове этой процедуры надо учитывать то, что имя файла будет сформировано путем добавления маркера времени вида yyyymmdd_HHMMSSttt и расширения .bck к имени файла переданного в строке filename.
procedure DelayMiliseconds(amount : integer);
Процедура формирует задержку выполнения скрипта на amount миллисекунд.
procedure ECUReset;
Процедура вызывает перезапуск блока путем имитации цикла выключение-включение зажигания.
function UploadZDC(filename,DataSetNameToUpload : string ; EraseFullMem : boolean) : string;
Функция осуществляет загрузку датасета DataSetNameToUpload из файла с контейнером ZDC, имя которого передается в виде строки filename. Выполнение команды Erase Full Memory перед записью контейнера определяется переменной EraseFullMem. Файл ZDC должен находится в одной папке со скриптом. Файл ZDC должен быть привязан к адаптеру VCP.
function UploadZDCRAW(login, Alfid, StartAdr, dataformat, datatoupload : string ; generation : integer; Erasefullmem : boolean) : string ;
Функция осуществляет загрузку датасета, переданного в виде строки datatoupload. Код доступа, ALFID, начальный адрес загрузки, формат и флаг необходимости выполнения команды Erase Full Memory перед записью контейнера определяется передачей параметров login, Alfid, dataformat, generation и Erasefullmem соответственно.
function ChangeDiagSessionRaw(RawSession : String) : boolean ;
Функция переключает диагностической сессию на тип, переданный в качестве параметра RawSession. Как вы наверное уже знаете, существует несколько типов сессий, от выбора которого меняется доступный функционал взаимодействия с выбранным блоком по CAN шине.
function getApplVersion : integer ;
Функция возвращает текущую версию VCP System.
function WaitForCANAnswer(data : string; pos : integer; time : integer) : integer ;
Функция ожидает получение подстроки data по CAN шине начиная с позиции pos за время не превышающее интервал, указанный в параметре time. Функция возвращает 1 в случае успеха и 0 в противном случае. При использовании функции следует учитывать внутренний формат CAN фрейма в VCP System вида AAALD[D], где:
- AAA – идентификатор CAN сообщения (CAN ID);
- L – длина фрейма;
- D[D] – байты данных
function getSeed(secmode : String) : string ;
Функция запрашивает значение seed для выбранного уровня доступа, переданного в параметре secmode. В случае ошибки функция возвращает пустую строку.
function sendKey(secmode, key : String) : boolean ;
Функция отправляет ключ, переданный в виде строки key для выбранного уровня доступа, переданного в параметре secmode.
Вместо заключения
Что ж на этом, пока все. Это были все процедуры и функции доступные в API VCP Scripter. В следующих заметках я обязательно подробнее расскажу о синтаксисе VCP Scripter и его особенностях. Не могу обещать создание какого-либо полезного скрипта в серии этих заметок, но вот один бесполезный будет точно, потому что на его примере я позволю себе классифицировать сложные места, которые могут возникать при создании скриптов, и подумать над вариантами их упрощения.
Оставайтесь с нами, ведь дальше будет интереснее…
Обновление от 2020.07.17: добавлено описание новых функций.