This commit is contained in:
tza 2024-05-01 12:34:45 +03:00
parent fcc3434920
commit e30a0cda65
4 changed files with 2 additions and 457 deletions

View File

@ -1,157 +0,0 @@
ВСЕ ЧТО ВЫ ДЕЛАЕТЕ СО СВОИМ АВТОМОБИЛЕМ, ВЫ ДЕЛАЕТЕ НА СВОЙ СТРАХ И РИСК.
ИСПОЛЬЗУЙТЕ ПРОГРАММУ НА ХОДУ ТОЛЬКО С ОСОБОЙ ОСТОРОЖНОСТЬЮ. НЕКОТОРЫЕ БЛОКИ, НАПРИМЕР ABS, МОГУТ РАБОТАТЬ ИНАЧЕ ПРИ ОТКРЫТОЙ ДИАГНОСТИЧЕСКОЙ СЕССИИ С НИМИ.
НЕПРАВИЛЬНОЕ ИСПОЛЬЗОВАНИЕ КОМАНД МОЖЕТ ПРИВЕСТИ К НЕКОРРЕКТНОЙ РАБОТЕ ЭБУ АВТОМОБИЛЯ
Возможности
- Сканирует и определяет типы ЭБУ на автомобилях Рено
- Считывает и показывает состояния, параметры и идентификации блоков
- Считывает и показывает текстовое описания ошибок ЭБУ, состояние ошибок и относящиеся к этим ошибкам параметры.
- Позволяет сбросить ошибки
- Позволяет выполнить некоторые типы команд
- Код программы открытый. Любой желающий может изменять, исправлять и развивать её, использовать любые отрывки кода по всему усмотрению.
- Работает под OS Windows, Linux, MacOS и Android
- Позволяет сгенерировать диагностическую документацию
Требования к оборудованию и ПО
- Компьютер с установленным ПО КЛИП (версии ниже 142 не тестировались, на 164 работает) Наличие аппаратной части не обязательно. Запускать и регистрировать ПО КЛИП не нежно.
- Адаптер ELM 327 и его аналоги на базе PIC процессора. (Китайские варианты с ARM ядром работать не будут или в лучшем случае покажут только ЭБУ впрыска)
- Python версии 2.7 с установленным модулем (pyserial)
Недостатки
- низкое качество кода
- поддерживаются не все команды ЭБУ
- не реализованы сценарии
- рассчитана на консоль с фиксированными размерами (90х30)
Установка на Windows
1. На компьютер с установленным ПО КЛИП устанавливаем Python 2.7 https://www.python.org/downloads/. При установке согласитесь с дефолтным месторасположением и с другими дефолтным опциями
2. Запустите CMD.EXE из меню ПУСК. Перейдите в директорию
 > cd c:\Python27\Scripts\
3. Разархивируйте архив со скриптом в папку C:\CLIP\Data\GenAppli так, чтобы там образовалась папка pyrenXXX и внутри нее скрипт pyren.py со всеми его модулями

(В дальнейшем для работы скрипта будут необходимы только файлы из директорий EcuRenault, Location и Vehicles. Все пути в скрипте относительные. Директорию GenAppli после копирования в нее скрипта можно переименовать и перенести в другое место или на другой компьютер, включая Linux и MacOS. )
4. Попробуйте запустить скрипт без параметров

 c:\CLIP\Data\GenAppli\pyren>pyren.py
скрипт должен показать свои параметры и список доступных COM портов. При первом запуске на Windows машинах скрипт доставит необходимые ему модули (компьютер должен быть в сети!!!!)
Подключение базы данных DDT2000
скопируйте директории ecus и graphics из DDT2000data туда, где лежат директории EcuRenault, Location и Vehicles
Подключение базы данных MTC и DocDb
Воспользуйтесь утилитой extract.py для извлечения всех необходимых данных с инсталляционного диска КЛИП
Скопируйте директорию BVMEXTRACTION туда где лежат директории EcuRenault, Location и Vehicles.
С инсталляционного диска скопируйте и распакуйте файл DocDb_XX.7ze с документацией на нужном языке.
Получившуюся директорию DocDb_XX скопируйте туда где лежат директории BVMEXTRACTION, EcuRenault, Location и Vehicles
Запуск скрипта на Linux и MacOS
- Директория GenAppli в которую был скопирован скрипт может быть просто скопирована с Windows машины на Linux или MacOS.
- Python 2.7 должен быть установлен.
- Установите модули PySerial
>sudo easy_install pyserial
Установка на Android
1. Установите и запустите скрипт на компьютере.
2. На android установите SL4A и Py4A. (Инструкция по установке https://github.com/kuri65536/python-for-android/blob/master/README.md)
3. Скопируйте с компьютера папки (EcuRenault, Location, Vehicles, pyrenXXX) и файл pyren_4a_launcher.py в папку sl4a/scripts на androide.
4. Запустите SL4A и оттуда pyren_4a_launcher.py (в тексте pyren_4a_launcher.py можно редактировать параметры)
Использование
Пример запуска скрипта:
c:\CLIP\Data\GenAppli\pyren>pyren.py -p COM6
Параметры запуска:
-p (Обязательный параметр). В нем нужно указать COM порт к которому подключен ELM или 192.168.0.10:35000 для WiFi
-s скорость порта. По умолчанию будет установлена 38400
-r Временное увеличение скорости порта на время работы скрипта. Используется команда "AT BRD"
-L язык описаний. По умолчанию устанавливается RU если КЛИП установлен с другим языком то нужно указать например -LGB. Запуск с несуществующим языком, например -LLL, отключит загрузку языковой базы
-vv показывает подробное описание параметров
-e ECUID выбор блока или список блоков для demo
--si всегда пробовать режим SlowInit
--cfc отключить автоматический FlowControl выполняемый ELM и делать его скриптом
--n1f отключает ускорение чтения данных с CAN
--log включает запись лог файлов. В директории Log создается два файла elm_xxxx и ecu_xxxx
--demo включает режим отладки. В этом режиме программу можно запускать без автомобиля и даже без ELM. Данные конечно никакие показываться не будут но можно будет побродить по менюшкам. ЭБУ при этом, берутся из файла savedEcus.p
--scan игнорирует наличие файла savedEcus.p и включает сканирование блоков при запуске программы.
--csv сохраняет данные считанные с ЭБУ в CSV файл для дальнейшего анализа, например в exel
--csv_only во время записи csv не показывать данные на экране
--csv_human человеческое описание колонок и значений
--usr_key добавляет пользовательские события в csv файл при нажатии клавиш
--dev временное переключение в "1086 : Development Session" при выполнении команд из DevList ['27','2E','30','31','32','34','35','36','37','3B','3D']
--dump при подключении к блоку сохранять его текущие настройки (команды 21* и 22*)
--can2 подключение к мультимедийной CAN (pin 13 и pin 12) (нужен адаптер с переключателем)
После первого сканирования будет создан файл savedEcus.p в котором сохраняться описания всех найденых блоков и при последующем запуске программы, сканирования происходить не будет. Скрипт был написан для личного использования и если вы постоянно будете подключаться к разным машинам, то вам постоянно нужно включать этот ключ или постоянно удалять файл savedEcus.p
Особенности интерфейса
- На Android можно изменить размер шрифта клавишами громкости.
- На некоторых экранах не помещаются все параметры, особенно когда используется ключ -vv в этом случае нужно нажимать на цифры чтобы включить нужную страницу.
- При стирании ошибок и запуске прочих команд нужно ввести слово “yes” чтобы подтвердить выполнение команды
Использование опции dump
ИСПОЛЬЗОВАНИЕ DUMP НЕ ГАРАНТИРУЕТ СОХРАНЕНИЕ И ВОССТАНОВЛЕНИЕ ПОЛНОЙ КОНФИГУРАЦИИ !!!
Использование ключа --dump позволяет сохранить текущую доступную конфигурацию блока при подключении к нему. Сохранение дампа может быть запущено из меню Dumps/Save DUMP модуля mod_ddt. dump-файлы далее могут быть использованы для просмотра конфигурации в demo-режиме и для восстановления старых настроек (возможно не всех).
Конфигурация сохраняется отдельно при подключении к блоку в pyren и в mod_ddt. mod_ddt, как правило, сохраняет более полную конфигурацию.
dump-файлы сохраняются в директории dumps.
Конфигурации сохраненные pyren имеют имя формата <unixTime>_<ecuID>.txt
Конфигурации сохраненные mod_ddt имеют имя формата <unixTime>_<xmlFileName>.txt
При использовании demo-режима, загружается последний из имеющихся файлов с максимальным значением unixTime. mod_ddt, в demo-режиме, позволяет загрузить любой из имеющихся dump-файлов для текущего xml, через меню Dumps.
Откат (Roll Back) конфигурации.
Функция заускается из меню Dumps/RollBack модуля mod_ddt. Выберите конфигурацию к которой нужно вернуться.
Функция определит разницу между выбранной конфигурацие и текущей (считанной из модуля в подключенном режиме или из последнего dump-файла в demo-режие).
На основе выявленной разницы, функция предложит список команд для "отката" к прежней конфигурации и предложит применить эти команды.
Для применения предложенных команд необходимо предварительно переключиться в Экспертный режим.
Предостережение!!!
ИСПОЛЬЗОВАНИЕ DUMP НЕ ГАРАНТИРУЕТ СОХРАНЕНИЕ И ВОССТАНОВЛЕНИЕ ПОЛНОЙ КОНФИГУРАЦИИ !!!
- Перед применением проверьте предложенные команды
- Из-за определнных сложностей, для модулей std_a команды отката могут быть определены неполно или даже неправильно! Тщательно проверьте предложенные команды.
- В процессе восстановления команды будут подаваться с фиксированной задержкой 1 секунда

View File

@ -17,8 +17,6 @@ from mod_elm import snat
from mod_elm import dnat
from mod_elm import AllowedList
from mod_elm import pyren_time
if mod_globals.os != 'android':
from mod_ddt import DDT
import mod_globals
import mod_db_manager
@ -152,10 +150,6 @@ class ECU:
self.elm.start_session( self.ecudata['startDiagReq'] )
if mod_globals.os == 'android' or mod_globals.opt_csv:
if self.ecudata['pin'].lower()=='can' and self.DataIds and mod_globals.opt_performance:
self.elm.checkModulePerformaceLevel(self.DataIds)
print("Done")
global ecudump
@ -348,7 +342,7 @@ class ECU:
menu = []
cmds = []
for dr in datarefs:
datastr = dr.name;
datastr = dr.name
if dr.type=='State':
datastr = self.States[dr.name].name + 'States not supported on one screen with commands'
if dr.type=='Parameter':
@ -1296,293 +1290,3 @@ def find_real_ecuid( eid ):
eid = eid.upper().replace('.XML','')
return eid, fastinit, slowinit, protocol, candst, startDiagReq
def main():
try:
import androidhelper as android
mod_globals.os = 'android'
except:
try:
import android
mod_globals.os = 'android'
except:
pass
if mod_globals.os == 'android':
ecuid = input('Enetr ECU ID:')
lanid = input('Language [RU]:')
if len(lanid)<2: lanid = 'RU'
sys.argv = sys.argv[:1]
sys.argv.append(ecuid)
sys.argv.append(lanid)
sys.argv.append('TORQ')
if len(sys.argv)<3:
print("Usage: mod_ecu.py <ID> <language> [torq] [nochk]")
print("Example:")
print(" mod_ecu.py 10016 RU ")
sys.exit(0)
ecuid = sys.argv[1]
lanid = sys.argv[2]
mod_db_manager.find_DBs()
if len(ecuid)==5:
ecuid, fastinit, slowinit, protocol, candst, startDiagReq = find_real_ecuid(ecuid)
sys.argv[1] = ecuid
Defaults = {}
Parameters = {}
States = {}
Identifications = {}
Commands = {}
Services = {}
Mnemonics = {}
print("Loading language ")
sys.stdout.flush()
lang = optfile("Location/DiagOnCAN_"+lanid+".bqm",True)
print("Done")
sys.stdout.flush()
fgfile = "EcuRenault/Sessions/FG"+ecuid+".xml"
sgfile = "EcuRenault/Sessions/SG"+ecuid+".xml"
mdom = xml.dom.minidom.parse(mod_db_manager.get_file_from_clip(fgfile))
mdoc = mdom.documentElement
print("Loading optimyzer")
sys.stdout.flush()
#opt_file = optfile(mod_db_manager.get_file_from_clip(sgfile))
opt_file = optfile(sgfile)
print("Loading defaults")
df_class = ecu_defaults ( Defaults, mdoc, opt_file.dict, lang.dict )
print("Loading parameters")
pr_class = ecu_parameters ( Parameters, mdoc, opt_file.dict, lang.dict )
print("Loading states")
st_class = ecu_states ( States, mdoc, opt_file.dict, lang.dict )
print("Loading identifications")
id_class = ecu_identifications( Identifications, mdoc, opt_file.dict, lang.dict )
print("Loading commands")
cm_class = ecu_commands ( Commands, mdoc, opt_file.dict, lang.dict )
print("Loading mnemonics")
mm_class = ecu_mnemonics ( Mnemonics, mdoc, opt_file.dict, lang.dict )
#for p in Parameters.values():
# print p
#for s in States.values():
# print s
#for m in Mnemonics.values():
# print m
if len(sys.argv)==3:
print()
print("Defaults")
print()
for i in sorted(Defaults.keys()):
print(pyren_encode( Defaults[i].name+"["+i+"] "+Defaults[i].label ))
print()
print("Parameters")
print()
for i in sorted(Parameters.keys()):
print(pyren_encode( Parameters[i].codeMR+"["+i+"] "+Parameters[i].label ))
print()
print("States")
print()
for i in sorted(States.keys()):
print(pyren_encode( States[i].codeMR+"["+i+"] "+States[i].label ))
print()
print("Identifications")
print()
for i in sorted(Identifications.keys()):
print(pyren_encode( Identifications[i].codeMR+"["+i+"] "+Identifications[i].label ))
print()
print("Commands")
print()
for i in sorted(Commands.keys()):
print(pyren_encode( Commands[i].codeMR+"["+i+"] "+Commands[i].label ))
sys.exit(0)
if len(sys.argv)>3 and sys.argv[3].upper()!='TORQ':
sys.exit(0)
family = sys.argv[1][:2]
eindex = sys.argv[1][2:]
if len(candst)>1:
sss = snat[F2A[family]]
ddd = dnat[F2A[family]]
filename = "PR_"+ddd+"_"+sss+"_"+eindex+"_"+sys.argv[2]+".csv"
else:
sss = '82'+F2A[family]+'F1'
ddd = '82'+F2A[family]+'F1'
filename = "PR_"+F2A[family]+"_"+eindex+"_"+sys.argv[2]+".csv"
ext_path = '/storage/emulated/0/.torque/extendedpids/'
if mod_globals.os=='android':
if not os.path.exists(ext_path):
os.makedirs( ext_path, exist_ok=True )
filename = ext_path+filename
cf = open( filename, "w")
line = "%s,%s,%s,%s,%s,%s,%s,%s\n"%("name","ShortName","ModeAndPID","Equation","Min Value","Max Value","Units","Header")
cf.write( line )
memIt = []
for i in sorted(Parameters.keys()):
if Parameters[i].codeMR in memIt:
continue
else:
memIt.append(Parameters[i].codeMR)
m = Parameters[i].mnemolist[0]
if len(Parameters[i].mnemolist)!=1:
continue
if '?' in Parameters[i].computation:
if len(sys.argv)==5 and sys.argv[4].upper()=='NOCHK':
pass
else:
continue
if Mnemonics[m].bitsLength=='':
continue
if Mnemonics[m].startBit=='':
continue
if Mnemonics[m].startByte=='':
continue
equ = gen_equ( Mnemonics[m] )
c_name = Parameters[i].label.replace(',','.')
c_short = Parameters[i].codeMR
c_pid = Mnemonics[m].request
c_equ = Parameters[i].computation.replace( m, equ )
c_min = Parameters[i].min
c_max = Parameters[i].max
c_unit = Parameters[i].unit
line = '"PR_%s","%s","%s","%s","%s","%s","%s","%s"\n'%(c_name,c_short,c_pid,c_equ,c_min,c_max,c_unit,ddd)
cf.write( line )
memIt = []
for i in sorted(States.keys()):
if States[i].codeMR in memIt:
continue
else:
memIt.append(States[i].codeMR)
m = States[i].mnemolist[0]
if len(States[i].mnemolist)!=1:
continue
if Mnemonics[m].bitsLength=='':
continue
if Mnemonics[m].startBit=='':
continue
if Mnemonics[m].startByte=='':
continue
equ = gen_equ( Mnemonics[m] )
c_name = States[i].label.replace(',','.')
c_short = States[i].codeMR
c_pid = Mnemonics[m].request
if len(sys.argv)==5 and sys.argv[4].upper()=='NOCHK':
c_equ = States[i].computation.replace( m, equ )
else:
c_equ = equ
c_min = '0'
c_max = '0'
c_unit = ''
line = '"ST_%s","%s","%s","%s","%s","%s","%s","%s"\n'%(c_name,c_short,c_pid,c_equ,c_min,c_max,c_unit,ddd)
cf.write( line )
cf.close()
print()
print("File:", filename, "created")
print()
# fastinit, slowinit, protocol, candst
can250init = "ATAL\\nATSH"+ddd+"\\nATCRA"+sss+"\\nATFCSH"+ddd+"\\nATFCSD300000\\nATFCSM1\\nATSP8\\n"+startDiagReq
can500init = "ATAL\\nATSH"+ddd+"\\nATCRA"+sss+"\\nATFCSH"+ddd+"\\nATFCSD300000\\nATFCSM1\\nATSP6\\n"+startDiagReq
slow05init = "ATSH81"+F2A[family]+"F1\\nATSW96\\nATIB10\\nATSP4\\nATSI\\n"+startDiagReq
fast10init = "ATSH81"+F2A[family]+"F1\\nATSW96\\nATIB10\\nATSP5\\nATFI\\n"+startDiagReq
if len(candst)>1:
print("Init string for CAN 500:")
print(can500init)
print()
print("Init string for CAN 250:")
print(can250init)
print()
if len(fastinit)>1:
print("Init string for Engine K-line (FAST INIT):")
print(fast10init)
print()
if len(slowinit)>1:
print("Init string for Engine K-line (SLOW INIT):")
print(slow05init)
print()
# make profile for torque
profilename = str(int(time.time()))+'.tdv'
veh_path = '/storage/emulated/0/.torque/vehicles/'
if mod_globals.os=='android':
if not os.path.exists(veh_path):
os.makedirs( veh_path, exist_ok=True )
profilename = veh_path+str(int(time.time()))+'.tdv'
prn = open( profilename, "w")
prn.write( '#This is an ECU profile generated by pyren\n' )
prn.write( 'fuelType=0\n' )
prn.write( 'obdAdjustNew=1.0\n' )
prn.write( 'lastMPG=0.0\n' )
prn.write( 'tankCapacity=295.5\n' )
prn.write( 'volumetricEfficiency=85.0\n' )
prn.write( 'weight=1400.0\n' )
prn.write( 'odoMeter=0.0\n' )
prn.write( 'adapterName=OBDII [00\:00\:00\:00\:00\:0]\n' )
prn.write( 'adapter=00\:00\:00\:00\:00\:00\n' )
prn.write( 'boostAdjust=0.0\n' )
prn.write( 'mpgAdjust=1.0\n' )
prn.write( 'fuelCost=0.18000000715255737\n' )
prn.write( 'ownProfile=false\n' )
prn.write( 'displacement=1.6\n' )
prn.write( 'tankUsed=147.75\n' )
prn.write( 'lastMPGCount=0\n' )
prn.write( 'maxRpm=7000\n' )
prn.write( 'fuelDistance=0.0\n' )
prn.write( 'fuelUsed=0.0\n' )
prn.write( 'alternateHeader=true\n' )
prn.write( ('name=PR_'+ecuid+'\n') )
if len(candst)>1:
prn.write( ('customInit='+can500init.replace('\\','\\\\')+'\n') )
prn.write( 'preferredProtocol=7\n' )
elif len(fastinit)>1:
prn.write( ('customInit='+fast10init.replace('\\','\\\\')+'\n') )
prn.write( 'preferredProtocol=6\n' )
else:
prn.write( ('customInit='+slow05init.replace('\\','\\\\')+'\n') )
prn.write( 'preferredProtocol=5\n' )
prn.close()
print()
print("Torque profile:", profilename, "created")
print()
if __name__ == "__main__":
main()

View File

@ -88,8 +88,6 @@ class ScanEcus:
except ValueError:
pass
xmlf = mod_db_manager.get_file_from_clip(file)
DOMTree = xml.dom.minidom.parse(mod_db_manager.get_file_from_clip(file))
vh = DOMTree.documentElement
if vh.hasAttribute("defaultText"):

View File

@ -236,7 +236,7 @@ def optParser():
mod_globals.opt_ecuid = options.ecuid
mod_globals.opt_speed = int(options.speed)
mod_globals.opt_rate = int(options.rate)
mod_globals.opt_lang = options.lang
mod_globals.opt_lang = options.lang.strip()
mod_globals.opt_car = options.car
mod_globals.opt_log = options.logfile
mod_globals.opt_demo = options.demo