1422 lines
50 KiB
Python
Executable File
1422 lines
50 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import sys, os
|
|
import operator
|
|
import ast
|
|
import gc
|
|
import time
|
|
|
|
import mod_ddt_utils
|
|
import mod_utils
|
|
import mod_db_manager
|
|
|
|
from shutil import copyfile
|
|
|
|
|
|
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])))
|
|
|
|
import mod_globals
|
|
import mod_scan_ecus
|
|
import mod_ddt_ecu
|
|
import mod_elm
|
|
|
|
try:
|
|
# Python2
|
|
import tkinter as tk
|
|
import tkinter.ttk
|
|
import tkinter.font
|
|
import tkinter.messagebox
|
|
import tkinter.filedialog
|
|
import tkinter.simpledialog
|
|
|
|
except ImportError:
|
|
# Python3
|
|
import tkinter as tk
|
|
import tkinter.ttk as ttk
|
|
import tkinter.font
|
|
import tkinter.messagebox
|
|
import tkinter.filedialog
|
|
|
|
from mod_ddt_ecu import DDTECU
|
|
from mod_ddt_screen import DDTScreen
|
|
|
|
import xml.etree.ElementTree as et
|
|
|
|
from xml.dom.minidom import parse
|
|
import xml.dom.minidom
|
|
|
|
mod_globals.os = os.name
|
|
|
|
if mod_globals.os == 'nt':
|
|
import pip
|
|
|
|
try:
|
|
import serial
|
|
except ImportError:
|
|
pip.main(['install', 'pyserial'])
|
|
|
|
else:
|
|
# let's try android
|
|
try:
|
|
import androidhelper as android
|
|
|
|
mod_globals.os = 'android'
|
|
except:
|
|
try:
|
|
import android
|
|
|
|
mod_globals.os = 'android'
|
|
except:
|
|
pass
|
|
|
|
if mod_globals.os != 'android':
|
|
try:
|
|
import serial
|
|
from serial.tools import list_ports
|
|
# import ply
|
|
except ImportError:
|
|
print("\n\n\n\tPleas install additional modules")
|
|
print("\t\t>sudo easy_install pyserial")
|
|
sys.exit()
|
|
|
|
from mod_elm import ELM
|
|
from mod_optfile import *
|
|
from mod_utils import *
|
|
|
|
|
|
class DDT():
|
|
decu = None # ddt ecu
|
|
cecu = None # chosen ecu
|
|
|
|
def __init__(self, elm, cecu, langmap={}):
|
|
self.elm = elm
|
|
self.cecu = cecu
|
|
|
|
clearScreen()
|
|
print("Starting DDT process")
|
|
|
|
# make or load ddt ecu
|
|
decucashfile = "./cache/ddt_" + cecu['ModelId'] + ".p"
|
|
|
|
if os.path.isfile(decucashfile) and mod_globals.opt_ddtxml == '': # if cache exists and no xml defined
|
|
self.decu = pickle.load(open(decucashfile, "rb")) # load it
|
|
else: # else
|
|
self.decu = DDTECU(self.cecu) # init class
|
|
self.decu.setELM(self.elm) # define ELM for it
|
|
self.decu.scanECU() # scan and loading original data for chosen ECU
|
|
self.decu.setELM(None) # clear elm before serialization
|
|
if len(self.decu.ecufname) > 0:
|
|
pickle.dump(self.decu, open(decucashfile, "wb")) # and save cache
|
|
|
|
self.decu.setELM(self.elm) # re-define ELM
|
|
self.decu.setLangMap(langmap)
|
|
|
|
if len(self.decu.ecufname) == 0:
|
|
return
|
|
|
|
if '/' in self.decu.ecufname:
|
|
xfn = self.decu.ecufname[:-4].split('/')[-1]
|
|
else:
|
|
xfn = self.decu.ecufname[:-4].split('\\')[-1]
|
|
|
|
dumpIs = False
|
|
for root, dirs, files in os.walk("./dumps"):
|
|
for f in files:
|
|
if ('_' + xfn + '.') in f:
|
|
dumpIs = True
|
|
break
|
|
|
|
if not mod_globals.opt_demo and not dumpIs and not mod_globals.opt_dump:
|
|
answer = input('Save dump ? [y/n] : ')
|
|
if 'N' in answer.upper():
|
|
dumpIs = True
|
|
|
|
if mod_globals.opt_demo:
|
|
print("Loading dump")
|
|
self.decu.loadDump()
|
|
elif mod_globals.opt_dump or not dumpIs:
|
|
print("Saving dump")
|
|
self.decu.saveDump()
|
|
|
|
# Load XML
|
|
if not self.decu.ecufname.startswith(mod_globals.ddtroot):
|
|
tmp_f_name = self.decu.ecufname.split('/')[-1]
|
|
self.decu.ecufname = 'ecus/'+tmp_f_name
|
|
|
|
if not mod_db_manager.file_in_ddt(self.decu.ecufname):
|
|
print("No such file: ", self.decu.ecufname)
|
|
return None
|
|
|
|
ns = {'ns0': 'http://www-diag.renault.com/2002/ECU',
|
|
'ns1': 'http://www-diag.renault.com/2002/screens'}
|
|
|
|
tree = et.parse(mod_db_manager.get_file_from_ddt(self.decu.ecufname))
|
|
xdoc = tree.getroot()
|
|
|
|
# Show screen
|
|
print("Show screen")
|
|
scr = DDTScreen(self.decu.ecufname, xdoc, self.decu)
|
|
|
|
del scr
|
|
del self.decu
|
|
|
|
def __del__(self):
|
|
# debug
|
|
# print sys.getrefcount(self.elm)
|
|
del self.elm
|
|
del self.cecu
|
|
|
|
|
|
def optParser():
|
|
'''Parsing of command line parameters. User should define at least com port name'''
|
|
'''Not used in current version'''
|
|
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser(
|
|
# usage = "%prog -p <port> [options]",
|
|
version="mod_ddt Version 0.9.q",
|
|
description="mod_ddt - python program for diagnostic Renault cars"
|
|
)
|
|
|
|
parser.add_argument('-p',
|
|
help="ELM327 com port name",
|
|
dest="port",
|
|
default="")
|
|
|
|
parser.add_argument("-r",
|
|
help="com port rate during diagnostic session {38400[default],57600,115200,230400,500000}",
|
|
dest="rate",
|
|
default="38400", )
|
|
|
|
parser.add_argument("-a",
|
|
help="functional address of ecu",
|
|
dest="ecuAddr",
|
|
default="")
|
|
|
|
parser.add_argument("-i",
|
|
help="interface protocol [can250|250|can500|500|kwpS|S|kwpF|F]",
|
|
dest="protocol",
|
|
default='500')
|
|
|
|
parser.add_argument("-L",
|
|
help="language option {RU[default],GB,FR,IT,...}",
|
|
dest="lang",
|
|
default="RU")
|
|
|
|
parser.add_argument("--cfc",
|
|
help="turn off automatic FC and do it by script",
|
|
dest="cfc",
|
|
default=False,
|
|
action="store_true")
|
|
|
|
parser.add_argument("--n1c",
|
|
help="turn off L1 cache",
|
|
dest="n1c",
|
|
default=False,
|
|
action="store_true")
|
|
|
|
parser.add_argument("--log",
|
|
help="log file name",
|
|
dest="logfile",
|
|
default="")
|
|
|
|
parser.add_argument("--xml",
|
|
help="xml file name",
|
|
dest="ddtxml",
|
|
default="")
|
|
|
|
parser.add_argument("--demo",
|
|
help="for debuging purpose. Work without car and ELM",
|
|
dest="demo",
|
|
default=False,
|
|
action="store_true")
|
|
|
|
parser.add_argument("--dump",
|
|
help="dump responces from all 21xx and 22xxxx requests",
|
|
dest="dump",
|
|
default=True,
|
|
action="store_true")
|
|
|
|
parser.add_argument("--exp",
|
|
help="swith to Expert mode (allow to use buttons in DDT)",
|
|
dest="exp",
|
|
default=False,
|
|
action="store_true")
|
|
|
|
options = parser.parse_args()
|
|
|
|
if not options.port and mod_globals.os != 'android':
|
|
parser.print_help()
|
|
iterator = sorted(list(list_ports.comports()))
|
|
print("")
|
|
print("Available COM ports:")
|
|
for port, desc, hwid in iterator:
|
|
print("%-30s \n\tdesc: %s \n\thwid: %s" % (port, desc.decode("windows-1251"), hwid))
|
|
print("")
|
|
exit(2)
|
|
else:
|
|
mod_globals.opt_port = options.port
|
|
mod_globals.opt_ecuAddr = options.ecuAddr.upper()
|
|
mod_globals.opt_rate = int(options.rate)
|
|
mod_globals.opt_lang = options.lang
|
|
mod_globals.opt_log = options.logfile
|
|
mod_globals.opt_demo = options.demo
|
|
mod_globals.opt_dump = options.dump
|
|
mod_globals.opt_exp = options.exp
|
|
mod_globals.opt_cfc0 = options.cfc
|
|
mod_globals.opt_n1c = options.n1c
|
|
mod_globals.opt_ddtxml = options.ddtxml
|
|
if 'S' in options.protocol.upper():
|
|
mod_globals.opt_protocol = 'S'
|
|
elif 'F' in options.protocol.upper():
|
|
mod_globals.opt_protocol = 'F'
|
|
elif '250' in options.protocol:
|
|
mod_globals.opt_protocol = '250'
|
|
elif '500' in options.protocol:
|
|
mod_globals.opt_protocol = '500'
|
|
else:
|
|
mod_globals.opt_protocol = '500'
|
|
|
|
class DDTLauncher():
|
|
def __init__(self):
|
|
|
|
self.eculist = mod_ddt_utils.loadECUlist()
|
|
self.carecus = []
|
|
|
|
self.root = tk.Tk()
|
|
self.root.title("mod_ddt Launcher")
|
|
self.style = tkinter.ttk.Style ()
|
|
self.style.theme_use ('classic')
|
|
|
|
self.var_dump = tk.BooleanVar()
|
|
self.var_log = tk.BooleanVar()
|
|
self.var_cfc = tk.BooleanVar()
|
|
self.var_can2 = tk.BooleanVar()
|
|
|
|
self.var_portList = []
|
|
self.var_speedList = []
|
|
|
|
self.var_port = tk.StringVar()
|
|
self.var_speed = tk.StringVar()
|
|
|
|
self.var_logName = tk.StringVar()
|
|
|
|
self.elm = None
|
|
self.save = mod_ddt_utils.settings()
|
|
self.loadSettings()
|
|
|
|
self.currentEcu = None
|
|
self.v_xmlList = []
|
|
self.v_dumpList = []
|
|
|
|
self.root.rowconfigure(0, weight=1)
|
|
self.root.rowconfigure(1, weight=1)
|
|
self.root.columnconfigure(0, weight=1, minsize=300)
|
|
self.root.columnconfigure(1) # not stretchable
|
|
self.root.columnconfigure(2, weight=3, minsize=300)
|
|
|
|
optsGrid = {'ipadx': 0, 'ipady': 0, 'sticky': 'nswe'}
|
|
optsGrid_w = {'ipadx': 0, 'ipady': 0, 'sticky': 'w'}
|
|
optsGrid_e = {'ipadx': 0, 'ipady': 0, 'sticky': 'e'}
|
|
btn_style = { 'activebackground':"#d9d9d9",
|
|
'activeforeground':"#000000",
|
|
'background':"#d9d9d9",
|
|
'foreground':"#000000",
|
|
'highlightbackground':"#d9d9d9"}
|
|
|
|
ent_style = { 'background':"#FFFFFF",
|
|
'foreground':"#000000",
|
|
'highlightbackground':"#d9d9d9"}
|
|
|
|
self.tf = tk.Frame(self.root)
|
|
self.tf.grid(row=0, column=0, **optsGrid )
|
|
|
|
self.tf.rowconfigure(0) # not stretchable
|
|
self.tf.rowconfigure(1, weight=1)
|
|
self.tf.columnconfigure(0, weight=1)
|
|
self.tf.columnconfigure(1)
|
|
|
|
self.filterText = tk.StringVar()
|
|
self.filtentry = tk.Entry(self.tf, textvariable=self.filterText, **ent_style)
|
|
self.filtentry.bind('<Return>', self.fltBtnClick)
|
|
self.filtentry.grid(row=0, column=0, **optsGrid)
|
|
|
|
self.filtbutton = tk.Button(self.tf, text="Filter", command=self.fltBtnClick, **btn_style)
|
|
self.filtbutton.grid(row=0, column=1, **optsGrid)
|
|
|
|
self.ptree = tkinter.ttk.Treeview(self.tf, columns = ['name','segment'], height=10)
|
|
self.ptree.grid(row=1, column=0, columnspan = 2, **optsGrid)
|
|
|
|
self.vsb = tkinter.ttk.Scrollbar(self.root, orient="vertical", command=self.ptree.yview)
|
|
self.vsb.grid(row=0, column=1, **optsGrid)
|
|
self.ptree.configure(yscrollcommand=self.vsb.set)
|
|
|
|
#self.ptree.bind('<Double-1>', self.OnDoubleClick)
|
|
self.ptree.bind('<ButtonRelease-1>', self.CarDoubleClick)
|
|
|
|
|
|
self.ptree.heading('#0', text='Project')
|
|
self.ptree.heading('name', text='Name', anchor='center')
|
|
self.ptree.heading('segment', text='Segm', anchor='e')
|
|
self.ptree.column('#0', minwidth=100, width=100, stretch=False)
|
|
self.ptree.column('#1', minwidth=150, width=150, stretch=True)
|
|
self.ptree.column('#2', minwidth=50, width=50, stretch=False)
|
|
|
|
self.mf = tk.Frame(self.root, background="#d9d9d9")
|
|
self.mf.grid(row=0, column=2, **optsGrid)
|
|
|
|
self.mf.rowconfigure(0)
|
|
self.mf.rowconfigure(1)
|
|
self.mf.rowconfigure(2)
|
|
self.mf.rowconfigure(3)
|
|
self.mf.rowconfigure(4)
|
|
self.mf.rowconfigure(5)
|
|
self.mf.rowconfigure(6, weight = 1)
|
|
self.mf.rowconfigure(7)
|
|
self.mf.rowconfigure(8)
|
|
self.mf.columnconfigure(0, weight = 1)
|
|
self.mf.columnconfigure(1, weight = 1)
|
|
self.mf.columnconfigure(2, weight = 1)
|
|
self.mf.columnconfigure(3, weight = 1)
|
|
|
|
|
|
self.l_db = tk.Label(self.mf, text='DB root:', background="#d9d9d9")
|
|
self.l_db.grid(row=0, column=0, **optsGrid_e)
|
|
self.l_db2 = tk.Label(self.mf, text=mod_globals.ddtroot, background="#d9d9d9")
|
|
self.l_db2.grid(row=0, column=1, **optsGrid_w)
|
|
|
|
self.l_pr = tk.Label(self.mf, text='Project:', background="#d9d9d9")
|
|
self.l_pr.grid(row=1, column=0, **optsGrid_e)
|
|
self.v_proj = tk.StringVar()
|
|
self.v_proj.set("")
|
|
self.e_proj = tk.Label(self.mf, textvariable=self.v_proj, background="#d9d9d9")
|
|
#self.e_proj.config(state=tk.DISABLED)
|
|
self.e_proj.grid(row=1, column=1, **optsGrid_w)
|
|
|
|
self.l_af = tk.Label(self.mf, text='Addressing:', background="#d9d9d9")
|
|
self.l_af.grid(row=2, column=0, **optsGrid_e)
|
|
self.v_addr = tk.StringVar()
|
|
self.v_addr.set("")
|
|
self.e_addr = tk.Label(self.mf, textvariable=self.v_addr, background="#d9d9d9")
|
|
#self.e_addr.config(state=tk.DISABLED)
|
|
self.e_addr.grid(row=2, column=1, **optsGrid_w)
|
|
|
|
self.l_pcan = tk.Label(self.mf, text='Primary CAN:', background="#d9d9d9")
|
|
self.l_pcan.grid(row=3, column=0, **optsGrid_e)
|
|
self.v_pcan = tk.StringVar()
|
|
self.v_pcan.set("")
|
|
self.e_pcan = tk.Label(self.mf, textvariable=self.v_pcan, background="#d9d9d9")
|
|
#self.e_pcan.config(state=tk.DISABLED)
|
|
self.e_pcan.grid(row=3, column=1, **optsGrid_w)
|
|
|
|
self.l_mcan = tk.Label(self.mf, text='Secondary CAN:', background="#d9d9d9")
|
|
self.l_mcan.grid(row=4, column=0, **optsGrid_e)
|
|
self.v_mcan = tk.StringVar()
|
|
self.v_mcan.set("")
|
|
self.e_mcan = tk.Label(self.mf, textvariable=self.v_mcan, background="#d9d9d9")
|
|
#self.e_mcan.config(state=tk.DISABLED)
|
|
self.e_mcan.grid(row=4, column=1, **optsGrid_w)
|
|
|
|
self.l_vi = tk.Label(self.mf, text='VIN or car name:', background="#d9d9d9")
|
|
self.l_vi.grid(row=5, column=0, **optsGrid_e)
|
|
self.v_vin = tk.StringVar()
|
|
self.v_vin.set("")
|
|
self.e_vin = tk.Entry(self.mf, textvariable=self.v_vin, **ent_style)
|
|
self.e_vin.grid(row=5, column=1, columnspan=3, **optsGrid)
|
|
|
|
####################################################################################
|
|
self.set_fr = tk.LabelFrame(self.mf, text="Settings", padx=5, background="#d9d9d9")
|
|
self.set_fr.grid(row=0, rowspan=5, column=2, columnspan=4, **optsGrid)
|
|
|
|
self.set_fr.rowconfigure(0)
|
|
self.set_fr.rowconfigure(1)
|
|
self.set_fr.rowconfigure(2)
|
|
self.set_fr.columnconfigure(0, weight=1)
|
|
self.set_fr.columnconfigure(1, weight=1)
|
|
self.set_fr.columnconfigure(2, weight=1)
|
|
|
|
self.port_lbl = tk.Label(self.set_fr, text='ELM:', background="#d9d9d9")
|
|
self.port_lbl.grid(row=0, column=0, **optsGrid_e)
|
|
|
|
self.portList = tkinter.ttk.Combobox(self.set_fr)
|
|
self.portList.grid(row=0, column=1, **optsGrid)
|
|
self.portList.configure(values=self.var_portList)
|
|
self.portList.configure(textvariable=self.var_port)
|
|
self.portList.configure(takefocus="")
|
|
|
|
self.speedList = tkinter.ttk.Combobox(self.set_fr, width=6)
|
|
self.speedList.grid(row=0, column=2, **optsGrid_w)
|
|
self.speedList.configure(values=self.var_speedList)
|
|
self.speedList.configure(textvariable=self.var_speed)
|
|
self.speedList.configure(takefocus="")
|
|
|
|
self.log_lbl = tk.Label(self.set_fr, text='Log:', background="#d9d9d9")
|
|
self.log_lbl.grid(row=1, column=0, **optsGrid_e)
|
|
|
|
self.logName = tk.Entry(self.set_fr, textvariable=self.var_logName, **ent_style)
|
|
self.logName.grid(row=1, column=1, **optsGrid)
|
|
|
|
self.logChk = tk.Checkbutton(self.set_fr, variable=self.var_log, background="#d9d9d9")
|
|
self.logChk.grid(row=1, column=2, **optsGrid_w)
|
|
|
|
self.dump_lbl = tk.Label(self.set_fr, text='Dump:', background="#d9d9d9")
|
|
self.dump_lbl.grid(row=2, column=0, **optsGrid_e)
|
|
|
|
self.dumpChk = tk.Checkbutton(self.set_fr, variable=self.var_dump, background="#d9d9d9")
|
|
self.dumpChk.grid(row=2, column=1, **optsGrid_w)
|
|
|
|
self.can2_lbl = tk.Label(self.set_fr, text='CAN2:', background="#d9d9d9")
|
|
self.can2_lbl.grid(row=2, column=1, **optsGrid_e)
|
|
|
|
self.can2Chk = tk.Checkbutton(self.set_fr, variable=self.var_can2, background="#d9d9d9")
|
|
self.can2Chk.grid(row=2, column=2, **optsGrid_w)
|
|
####################################################################################
|
|
|
|
self.btn_connect = tk.Button(self.mf, text="Connect selected ECU (ON-line)", command=self.ConnectBtnClick, **btn_style)
|
|
self.btn_connect.grid(row=6, column=0, columnspan=2, **optsGrid)
|
|
|
|
self.btn_connect = tk.Button(self.mf, text="Show selected ECU (OFF-line)", command=self.DemoBtnClick, **btn_style)
|
|
self.btn_connect.grid(row=6, column=3, **optsGrid)
|
|
|
|
self.btn_scan_all_car = tk.Button(self.mf, text="Scan all ECUs", command=self.ScanAllBtnClick, **btn_style)
|
|
self.btn_scan_all_car.grid(row=7, column=0, **optsGrid)
|
|
|
|
self.btn_scan_car = tk.Button(self.mf, text="Scan selected ECU", command=self.ScanSelectedBtnClick, **btn_style)
|
|
self.btn_scan_car.grid(row=7, column=1, **optsGrid)
|
|
|
|
self.btn_load_car = tk.Button(self.mf, text="Load car", command=self.LoadBtnClick, **btn_style)
|
|
self.btn_load_car.grid(row=7, column=2, **optsGrid)
|
|
|
|
self.btn_save_car = tk.Button(self.mf, text="Save car", command=self.SaveBtnClick, **btn_style)
|
|
self.btn_save_car.grid(row=7, column=3, **optsGrid)
|
|
|
|
self.progress = tkinter.ttk.Progressbar(self.mf, mode="determinate")
|
|
self.progress.grid(row=8, column=0, columnspan=4, **optsGrid)
|
|
|
|
self.df = tk.Frame(self.root, background='#d9d9d9')
|
|
self.df.grid(row=1, column=0, columnspan=3, **optsGrid )
|
|
|
|
self.df.rowconfigure(0) # not stretchable
|
|
self.df.columnconfigure(0, weight=1)
|
|
self.df.columnconfigure(1)
|
|
|
|
self.ecutree = tkinter.ttk.Treeview(self.df, columns = ['ISO8','XId','RId','Prot','Type','Name','XML','dump'], height=20)
|
|
self.ecutree.grid(row=0, column=0, **optsGrid)
|
|
|
|
self.vsb1 = tkinter.ttk.Scrollbar(self.df, orient="vertical", command=self.ecutree.yview)
|
|
self.vsb1.grid(row=0, column=1, **optsGrid)
|
|
self.ecutree.configure(yscrollcommand=self.vsb1.set)
|
|
|
|
self.ecutree.bind('<ButtonRelease-2>', self.EcuDoubleClick)
|
|
self.ecutree.bind('<Double-Button-1>', self.EcuDoubleClick)
|
|
|
|
self.ecutree.heading('#0', text='Addr')
|
|
self.ecutree.heading('#1', text='ISO8')
|
|
self.ecutree.heading('#2', text='XId')
|
|
self.ecutree.heading('#3', text='RId')
|
|
self.ecutree.heading('#4', text='Protocol')
|
|
self.ecutree.heading('#5', text='Type')
|
|
self.ecutree.heading('#6', text='Name')
|
|
self.ecutree.heading('#7', text='XML')
|
|
self.ecutree.heading('#8', text='dump')
|
|
self.ecutree.column('#0', minwidth=40, width=40, stretch=False)
|
|
self.ecutree.column('#1', minwidth=40, width=40, stretch=False)
|
|
self.ecutree.column('#2', minwidth=40, width=40, stretch=False)
|
|
self.ecutree.column('#3', minwidth=40, width=40, stretch=False)
|
|
self.ecutree.column('#4', minwidth=80, width=80, stretch=False)
|
|
self.ecutree.column('#5', minwidth=100, width=100, stretch=False)
|
|
self.ecutree.column('#6', minwidth=150, width=150, stretch=False)
|
|
self.ecutree.column('#7', minwidth=300, width=300, stretch=True)
|
|
self.ecutree.column('#8', minwidth=150, width=150, stretch=True)
|
|
|
|
self.pl = mod_ddt_utils.ddtProjects()
|
|
self.fltBtnClick() # show tree with apply clear filter
|
|
|
|
self.LoadCarFile("./savedCAR_prev.csv")
|
|
|
|
self.root.mainloop()
|
|
|
|
def __del__(self):
|
|
self.SaveBtnClick()
|
|
self.saveSettings()
|
|
|
|
def enableELM(self):
|
|
|
|
# print self.elm
|
|
if self.elm != None:
|
|
try:
|
|
self.elm.port.hdr.close()
|
|
del(self.elm)
|
|
self.elm = None
|
|
gc.collect()
|
|
except:
|
|
pass
|
|
|
|
self.applySettings()
|
|
|
|
try:
|
|
mod_globals.opt_demo = False
|
|
self.elm = ELM(mod_globals.opt_port, mod_globals.opt_speed, mod_globals.opt_log)
|
|
except:
|
|
result = tkinter.messagebox.askquestion("Warning", "ELM is not connected. Would you like to work OFF-line?", icon='warning')
|
|
if result == 'yes':
|
|
mod_globals.opt_demo = True
|
|
self.elm = ELM(mod_globals.opt_port, mod_globals.opt_speed, mod_globals.opt_log)
|
|
if mod_globals.opt_obdlink == True:
|
|
self.elm.ATCFC0 = False
|
|
mod_globals.opt_cfc0 = False
|
|
else:
|
|
raise Exception('elm is not connected')
|
|
return
|
|
|
|
# change serial port baud rate
|
|
if mod_globals.opt_speed < mod_globals.opt_rate and not mod_globals.opt_demo:
|
|
self.elm.port.soft_boudrate(mod_globals.opt_rate)
|
|
|
|
def LoadCarFile(self, filename):
|
|
if not os.path.isfile(filename):
|
|
return
|
|
with open(filename, 'r') as fin:
|
|
lines = fin.read().splitlines()
|
|
fin.close()
|
|
|
|
self.carecus = []
|
|
for l in lines:
|
|
l = l.strip()
|
|
if len(l)==0 or l.startswith('#'):
|
|
continue
|
|
li = l.split(';')
|
|
if li[0].lower()=='car':
|
|
self.v_proj.set(li[1])
|
|
self.v_addr.set(li[2])
|
|
self.v_pcan.set(li[3])
|
|
self.v_mcan.set(li[4])
|
|
self.v_vin.set(li[5])
|
|
else:
|
|
ecu = {}
|
|
ecu['undef'] = li[0]
|
|
ecu['addr'] = li[1]
|
|
ecu['iso8'] = li[2]
|
|
ecu['xid'] = li[3]
|
|
ecu['rid'] = li[4]
|
|
ecu['prot'] = li[5]
|
|
ecu['type'] = li[6]
|
|
ecu['name'] = li[7]
|
|
ecu['xml'] = li[8]
|
|
ecu['dump'] = li[9]
|
|
ecu['ses'] = li[10]
|
|
self.carecus.append(ecu)
|
|
|
|
self.renewEcuList()
|
|
|
|
def LoadBtnClick(self):
|
|
filename = tkinter.filedialog.askopenfilename(initialdir='./', title='Select file',
|
|
filetypes=[('csv files', '*.csv')])
|
|
self.LoadCarFile(filename)
|
|
return
|
|
|
|
def SaveBtnClick(self):
|
|
filename = './savedCAR_'+self.v_vin.get()+'.csv'
|
|
with open( filename, 'w') as fout:
|
|
car = ['car',self.v_proj.get(), self.v_addr.get(), self.v_pcan.get(), self.v_mcan.get(), self.v_vin.get()]
|
|
fout.write(';'.join(car)+'\n')
|
|
for ecu in self.carecus:
|
|
e = [ecu['undef'],
|
|
ecu['addr'],
|
|
ecu['iso8'],
|
|
ecu['xid'],
|
|
ecu['rid'],
|
|
ecu['prot'],
|
|
ecu['type'],
|
|
ecu['name'],
|
|
ecu['xml'],
|
|
ecu['dump'],
|
|
ecu['ses']]
|
|
fout.write(';'.join(e) + '\n')
|
|
fout.close()
|
|
|
|
copyfile(filename, "./savedCAR_prev.csv")
|
|
|
|
return
|
|
|
|
def setEcuAddress(self, ce, pro ):
|
|
# define ecudata
|
|
ecudata = {'idTx': ce['xid'],
|
|
'idRx': ce['rid'],
|
|
'slowInit': '',
|
|
'fastInit': '',
|
|
'ModelId': ce['addr'],
|
|
'ecuname': 'ddt_unknown',
|
|
}
|
|
if pro == 'CAN':
|
|
if ce['prot'] == 'CAN-250':
|
|
ecudata['protocol'] = 'CAN_250'
|
|
ecudata['brp'] = '01'
|
|
else:
|
|
ecudata['protocol'] = 'CAN_500'
|
|
ecudata['brp'] = '0'
|
|
|
|
ecudata['pin'] = 'can'
|
|
self.elm.set_can_addr(ce['addr'], ecudata)
|
|
|
|
if pro == 'KWP' or pro == 'ISO':
|
|
if ce['prot'] == 'KWP-FAST':
|
|
ecudata['protocol'] = 'KWP_Fast'
|
|
ecudata['fastInit'] = ce['addr']
|
|
ecudata['slowInit'] = ''
|
|
mod_globals.opt_si = False
|
|
elif ce['prot'] == 'ISO8' and ce['iso8'] != '':
|
|
ecudata['protocol'] = 'KWP_Slow'
|
|
ecudata['fastInit'] = ''
|
|
ecudata['slowInit'] = ce['iso8']
|
|
mod_globals.opt_si = True
|
|
else:
|
|
ecudata['protocol'] = 'KWP_Slow'
|
|
ecudata['fastInit'] = ''
|
|
ecudata['slowInit'] = ce['addr']
|
|
mod_globals.opt_si = True
|
|
|
|
ecudata['pin'] = 'iso'
|
|
self.elm.set_iso_addr(ce['addr'], ecudata)
|
|
|
|
def ScanAllBtnClick(self):
|
|
|
|
# Enable ELM
|
|
try:
|
|
self.enableELM()
|
|
except:
|
|
return
|
|
|
|
if self.elm==None or self.elm.port==0:
|
|
tkinter.messagebox.showinfo("ERROR", "ELM is not connected. You may work only offline.")
|
|
return
|
|
|
|
|
|
# for all carecus find can ecus, then k-line ecus
|
|
scansequence = ['CAN','KWP','ISO']
|
|
vins = {}
|
|
self.progress['maximum'] = len(self.carecus)+1
|
|
progressValue = 1
|
|
self.progress['value'] = progressValue
|
|
for pro in scansequence:
|
|
|
|
# init protocol
|
|
if pro == 'CAN':
|
|
self.elm.init_can()
|
|
else:
|
|
self.elm.init_iso()
|
|
|
|
for ce in self.carecus:
|
|
if pro in ce['prot'] or ce['prot']=='':
|
|
|
|
# set address
|
|
self.setEcuAddress(ce, pro)
|
|
|
|
progressValue = progressValue + 1
|
|
self.progress['value'] = progressValue
|
|
self.progress.update()
|
|
|
|
# get ID
|
|
(StartSession, DiagVersion, Supplier, Version, Soft, Std, VIN) = mod_scan_ecus.readECUIds(self.elm)
|
|
|
|
if DiagVersion=='' and DiagVersion=='' and Version=='' and Soft=='' and VIN=='':
|
|
continue
|
|
|
|
candlist = mod_ddt_ecu.ecuSearch(self.v_proj.get(), ce['addr'],
|
|
DiagVersion, Supplier, Soft, Version,
|
|
self.eculist, interactive = False)
|
|
ce['xml'] = candlist[0]
|
|
ce['ses'] = StartSession
|
|
ce['undef'] = '0'
|
|
tmp = self.getDumpListByXml(ce['xml'])
|
|
if len(tmp)>0:
|
|
ce['dump'] = tmp[-1]
|
|
else:
|
|
ce['dump'] = ''
|
|
|
|
|
|
# count most frequent VINs
|
|
if VIN!='':
|
|
if VIN not in list(vins.keys()):
|
|
vins[VIN] = 1
|
|
else:
|
|
vins[VIN] = vins[VIN] + 1
|
|
|
|
self.renewEcuList()
|
|
|
|
if self.v_vin.get()=='' and len(list(vins.keys())):
|
|
self.v_vin.set(max(iter(vins.items()), key=operator.itemgetter(1))[0])
|
|
|
|
self.progress['value'] = 0
|
|
return
|
|
|
|
def ScanSelectedBtnClick(self):
|
|
# Enable ELM
|
|
try:
|
|
self.enableELM()
|
|
except:
|
|
return
|
|
|
|
if self.elm==None or self.elm.port==0:
|
|
tkinter.messagebox.showinfo("ERROR", "ELM is not connected. You may work only offline.")
|
|
return
|
|
|
|
try:
|
|
item = self.ecutree.selection()[0]
|
|
e = self.ecutree.item(item)['values'][8]
|
|
except:
|
|
pass
|
|
|
|
ce = None
|
|
for ce in self.carecus:
|
|
if str(ce)==e:
|
|
break
|
|
|
|
self.currentEcu = self.carecus.index(ce)
|
|
|
|
if ce==None:
|
|
return
|
|
|
|
#ce = self.getSelectedECU()
|
|
|
|
# init protocol
|
|
if 'CAN' in ce['prot'] and ce['xid']!='' and ce['rid']!='':
|
|
pro = 'CAN'
|
|
else:
|
|
pro = 'KWP'
|
|
|
|
if pro == 'CAN':
|
|
self.elm.init_can()
|
|
else:
|
|
self.elm.init_iso()
|
|
|
|
# set address
|
|
self.setEcuAddress(ce, pro)
|
|
|
|
# get ID
|
|
(StartSession, DiagVersion, Supplier, Version, Soft, Std, VIN) = mod_scan_ecus.readECUIds(self.elm)
|
|
|
|
if DiagVersion=='' and Supplier=='' and Version=='' and Soft=='':
|
|
tkinter.messagebox.showinfo("INFO", "no response from this ECU")
|
|
return
|
|
|
|
candlist = mod_ddt_ecu.ecuSearch(self.v_proj.get(), ce['addr'],
|
|
DiagVersion, Supplier, Soft, Version,
|
|
self.eculist, interactive = False)
|
|
ce['xml'] = candlist[0]
|
|
ce['ses'] = StartSession
|
|
ce['undef'] = '0'
|
|
|
|
self.renewEcuList()
|
|
|
|
return
|
|
|
|
def ConnectBtnClick(self):
|
|
ecu = self.getSelectedECU()
|
|
if ecu==None or ecu['xml']=='':
|
|
tkinter.messagebox.showinfo("INFO", "Selected ECU is undefined. Please scan it first.")
|
|
return None
|
|
|
|
mod_globals.opt_demo = False
|
|
|
|
self.OpenECUScreens(ecu)
|
|
|
|
return
|
|
|
|
def getSelectedECU(self):
|
|
try:
|
|
item = self.ecutree.selection()[0]
|
|
line = self.ecutree.item(item)['values']
|
|
except:
|
|
if len(self.ecutree.get_children(""))==0:
|
|
tkinter.messagebox.showinfo("INFO", "Please select the project in the left list and then ECU in the bottom")
|
|
else:
|
|
tkinter.messagebox.showinfo("INFO", "Please select an ECU in the bottom list")
|
|
return None
|
|
|
|
ecu = ast.literal_eval(line[8])
|
|
|
|
return ecu
|
|
|
|
def OpenECUScreens(self, ce):
|
|
|
|
decu = None
|
|
|
|
# Enable ELM
|
|
try:
|
|
self.enableELM()
|
|
except:
|
|
return
|
|
|
|
if not mod_globals.opt_demo and self.var_dump.get():
|
|
mod_globals.opt_dump = True
|
|
|
|
ce = self.getSelectedECU()
|
|
|
|
# init protocol
|
|
if 'CAN' in ce['prot'] and ce['xid']!='' and ce['rid']!='':
|
|
pro = 'CAN'
|
|
else:
|
|
pro = 'KWP'
|
|
|
|
#check elm timeout
|
|
ct1 = time.time()
|
|
|
|
if pro == 'CAN':
|
|
self.elm.init_can()
|
|
else:
|
|
self.elm.init_iso()
|
|
|
|
ct2 = time.time()
|
|
|
|
if ct2-ct1 > 5:
|
|
tkinter.messagebox.showinfo("ERROR", "ELM is not responding well.")
|
|
return
|
|
|
|
# set address
|
|
self.setEcuAddress(ce, pro)
|
|
|
|
self.elm.start_session(ce['ses'])
|
|
|
|
# make or load ddt ecu
|
|
decucashfile = "./cache/ddt_" + ce['xml'][:-4] + ".p"
|
|
|
|
if os.path.isfile(decucashfile): # if cache exists and no xml defined
|
|
decu = pickle.load(open(decucashfile, "rb")) # load it
|
|
else: # else
|
|
decu = DDTECU(None) # init class
|
|
decu.loadXml('ecus/'+ce['xml'])
|
|
if len(decu.ecufname) > 0:
|
|
pickle.dump(decu, open(decucashfile, "wb")) # and save cache
|
|
|
|
decu.setELM(self.elm) # re-define ELM
|
|
|
|
if len(decu.ecufname) == 0:
|
|
return
|
|
|
|
if '/' in decu.ecufname:
|
|
xfn = decu.ecufname[:-4].split('/')[-1]
|
|
else:
|
|
xfn = decu.ecufname[:-4].split('\\')[-1]
|
|
|
|
dumpIs = False
|
|
for root, dirs, files in os.walk("./dumps"):
|
|
for f in files:
|
|
if (xfn + '.') in f:
|
|
dumpIs = True
|
|
break
|
|
|
|
#if not mod_globals.opt_demo and not dumpIs and not mod_globals.opt_dump:
|
|
# answer = raw_input('Save dump ? [y/n] : ')
|
|
# if 'N' in answer.upper():
|
|
# dumpIs = True
|
|
|
|
if mod_globals.opt_demo:
|
|
print("Loading dump")
|
|
if len(ce['dump'])==0:
|
|
decu.loadDump()
|
|
else:
|
|
decu.loadDump("./dumps/"+ce['dump'])
|
|
elif mod_globals.opt_dump:
|
|
ce['dump'] = self.guiSaveDump(decu)
|
|
for ec in self.carecus:
|
|
if ce['xml'][:-4] in ec['xml']:
|
|
ec['dump'] = ce['dump']
|
|
self.renewEcuList()
|
|
self.SaveBtnClick()
|
|
|
|
# Load XML
|
|
if not mod_db_manager.file_in_ddt(decu.ecufname):
|
|
print("No such file: ", decu.ecufname)
|
|
return None
|
|
|
|
ns = {'ns0': 'http://www-diag.renault.com/2002/ECU',
|
|
'ns1': 'http://www-diag.renault.com/2002/screens'}
|
|
|
|
tree = et.parse(mod_db_manager.get_file_from_ddt(decu.ecufname))
|
|
xdoc = tree.getroot()
|
|
|
|
# Show screen
|
|
print("Show screen")
|
|
scr = DDTScreen(decu.ecufname, xdoc, decu, top=True)
|
|
|
|
del scr
|
|
del decu
|
|
|
|
def guiSaveDump(self,decu):
|
|
''' save responces from all 21xx, 22xxxx commands '''
|
|
|
|
self.pdlg = tk.Toplevel()
|
|
self.pdlg.option_add ('*Dialog.msg.font', 'Courier\ New 12')
|
|
self.pdlg.geometry("256x100")
|
|
self.pdlg.title("Saving dump")
|
|
self.pdlg.configure(background="#d9d9d9")
|
|
|
|
v_cmd = tk.StringVar()
|
|
v_cmd.set("")
|
|
e_cmd = tk.Label(self.pdlg, textvariable=v_cmd, background="#d9d9d9")
|
|
e_cmd.pack(expand=1, fill=tk.X)
|
|
|
|
v_cnt = tk.StringVar()
|
|
v_cnt.set("")
|
|
e_cnt = tk.Label(self.pdlg, textvariable=v_cnt, background="#d9d9d9")
|
|
e_cnt.pack(expand=1, fill=tk.X)
|
|
|
|
progress = tkinter.ttk.Progressbar(self.pdlg, mode="determinate")
|
|
progress.pack(expand=1, fill=tk.X)
|
|
|
|
xmlname = decu.ecufname
|
|
if xmlname.upper().endswith('.XML'):
|
|
xmlname = xmlname[:-4]
|
|
|
|
if '/' in xmlname:
|
|
xmlname = xmlname.split('/')[-1]
|
|
else:
|
|
xmlname = xmlname.split('\\')[-1]
|
|
|
|
dumpFileName = str(int(time.time())) + '_' + xmlname + '.txt'
|
|
dumpPath = './dumps/' + dumpFileName
|
|
df = open(dumpPath, 'wt')
|
|
|
|
decu.elm.clear_cache()
|
|
|
|
max = len(list(decu.requests.keys()))
|
|
|
|
progress['maximum'] = max
|
|
progressValue = 1
|
|
progress['value'] = progressValue
|
|
|
|
im = ' from ' + str(max)
|
|
i = 0
|
|
for request in list(decu.requests.values()):
|
|
i = i + 1
|
|
progressValue = progressValue + 1
|
|
progress['value'] = progressValue
|
|
progress.update()
|
|
sys.stdout.flush()
|
|
if request.SentBytes[:2] in mod_elm.AllowedList + ['17', '19']:
|
|
if request.SentBytes[:2] == '19' and request.SentBytes[:2] != '1902':
|
|
continue
|
|
if request.SentBytes[:2] == '22' and len(request.SentBytes) < 6:
|
|
continue
|
|
v_cmd.set(request.SentBytes)
|
|
e_cmd.update()
|
|
v_cnt.set(str(i)+'/'+str(max))
|
|
e_cnt.update()
|
|
pos = chr(ord(request.SentBytes[0]) + 4) + request.SentBytes[1]
|
|
rsp = decu.elm.request(request.SentBytes, pos, False)
|
|
if ':' in rsp: continue
|
|
df.write('%s:%s\n' % (request.SentBytes, rsp))
|
|
|
|
df.close()
|
|
self.pdlg.destroy()
|
|
return dumpFileName
|
|
|
|
def DemoBtnClick(self):
|
|
|
|
ecu = self.getSelectedECU()
|
|
if ecu==None or ecu['xml']=='':
|
|
tkinter.messagebox.showinfo("INFO", "Selected ECU is undefined. Please scan it first.")
|
|
return None
|
|
|
|
mod_globals.opt_demo = True
|
|
|
|
self.OpenECUScreens(ecu)
|
|
|
|
return
|
|
|
|
def fltBtnClick(self, ev=None):
|
|
self.ptree.delete(*self.ptree.get_children())
|
|
|
|
ptrn = self.filterText.get().strip().lower()
|
|
|
|
for m in self.pl.plist:
|
|
self.ptree.insert('','end',iid=m['name'], text=m['name'], open=True)
|
|
for c in m['list']:
|
|
if len(ptrn)==0 or ptrn in str(c).lower():
|
|
self.ptree.insert(m['name'], 'end', iid = c['code'], text = c['code'], values=[c['name'],c['segment'],c['addr']])
|
|
|
|
def treeview_sort_column(self, tv, col, reverse):
|
|
l = [(tv.set(k, col), k) for k in tv.get_children('')]
|
|
l.sort(reverse=reverse)
|
|
|
|
# rearrange items in sorted positions
|
|
for index, (val, k) in enumerate(l):
|
|
tv.move(k, '', index)
|
|
|
|
# reverse sort next time
|
|
tv.heading(col, command=lambda: \
|
|
self.treeview_sort_column(tv, col, not reverse))
|
|
|
|
def CarDoubleClick(self, event):
|
|
try:
|
|
item = self.ptree.selection()[0]
|
|
line = self.ptree.item(item)['values']
|
|
self.addr = mod_ddt_utils.ddtAddressing(line[2])
|
|
self.v_proj.set(item)
|
|
self.v_addr.set(line[2])
|
|
self.v_vin.set('')
|
|
except:
|
|
return
|
|
|
|
tmpL = []
|
|
self.carecus = []
|
|
|
|
for e in self.addr.alist:
|
|
if e['Address']==0:
|
|
self.v_pcan.set(e['baudRate'])
|
|
continue
|
|
if e['Address']==255:
|
|
self.v_mcan.set(e['baudRate'])
|
|
continue
|
|
|
|
if 'en' in list(e['longname'].keys()):
|
|
longname = e['longname']['en']
|
|
else:
|
|
longname = list(e['longname'].values())[0]
|
|
|
|
if e['Address']:
|
|
v_addr = hex(int(e['Address']))[2:].upper()
|
|
if len(v_addr)==1:
|
|
v_addr = '0'+v_addr
|
|
else:
|
|
v_addr = ''
|
|
if e['ISO8']:
|
|
v_iso = hex(int(e['ISO8']))[2:].upper()
|
|
if len(v_iso)==1:
|
|
v_addr = '0'+v_iso
|
|
else:
|
|
v_iso = ''
|
|
if e['XId']:
|
|
if len(e['XId'])>6:
|
|
v_XId = hex(0x80000000+int(e['XId']))[2:].upper()
|
|
else:
|
|
v_XId = hex(int(e['XId']))[2:].upper()
|
|
else:
|
|
v_XId = ''
|
|
if e['RId']:
|
|
if len(e['RId'])>6:
|
|
v_RId = hex(0x80000000+int(e['RId']))[2:].upper()
|
|
else:
|
|
v_RId = hex(int(e['RId']))[2:].upper()
|
|
else:
|
|
v_RId = ''
|
|
|
|
if e['protocol']=='6' and (v_XId=='' or v_RId==''):
|
|
continue #
|
|
|
|
key = e['protocol'] + v_addr
|
|
|
|
if key in tmpL:
|
|
continue
|
|
|
|
tmpL.append(key)
|
|
|
|
v_prot = e['protocol']
|
|
if e['protocol']=='1':
|
|
v_prot = 'ISO8'
|
|
elif e['protocol']=='2' or e['protocol']=='3':
|
|
v_prot = 'KWP-SLOW'
|
|
elif e['protocol']=='4' or e['protocol']=='5':
|
|
v_prot = 'KWP-FAST'
|
|
elif e['protocol']=='6' and self.v_pcan.get()=='250000':
|
|
v_prot = 'CAN-250'
|
|
elif e['protocol']=='6':
|
|
v_prot = 'CAN-500'
|
|
|
|
ecu = {}
|
|
ecu['undef'] = '1'
|
|
ecu['addr'] = v_addr
|
|
ecu['iso8'] = v_iso
|
|
ecu['xid'] = v_XId
|
|
ecu['rid'] = v_RId
|
|
ecu['prot'] = v_prot
|
|
ecu['type'] = e['Name']
|
|
ecu['name'] = longname
|
|
ecu['xml'] = ''
|
|
ecu['dump'] = ''
|
|
ecu['ses'] = ''
|
|
self.carecus.append(ecu)
|
|
|
|
self.renewEcuList()
|
|
|
|
def EcuDoubleClick(self, event):
|
|
|
|
self.currentEcu = None
|
|
|
|
try:
|
|
item = self.ecutree.selection()[0]
|
|
e = self.ecutree.item(item)['values'][8]
|
|
except:
|
|
pass
|
|
|
|
ecu = None
|
|
for ecu in self.carecus:
|
|
if str(ecu)==e:
|
|
break
|
|
|
|
self.currentEcu = self.carecus.index(ecu)
|
|
|
|
if ecu==None:
|
|
return
|
|
|
|
self.ecudlg = tk.Toplevel()
|
|
self.ecudlg.option_add ('*Dialog.msg.font', 'Courier\ New 12')
|
|
#ecudlg.geometry("256x256")
|
|
self.ecudlg.title("Ecu settings")
|
|
self.ecudlg.configure(background="#d9d9d9")
|
|
|
|
optsGrid = {'ipadx': 0, 'ipady': 0, 'sticky': 'nswe'}
|
|
optsGrid_w = {'ipadx': 0, 'ipady': 0, 'sticky': 'w'}
|
|
optsGrid_e = {'ipadx': 0, 'ipady': 0, 'sticky': 'e'}
|
|
ent_style = { 'background':"#FFFFFF",
|
|
'foreground':"#000000",
|
|
'highlightbackground':"#d9d9d9"}
|
|
btn_style = { 'activebackground':"#d9d9d9",
|
|
'activeforeground':"#000000",
|
|
'background':"#d9d9d9",
|
|
'foreground':"#000000",
|
|
'highlightbackground':"#d9d9d9"}
|
|
|
|
l_type = tk.Label(self.ecudlg, text='Type:', background="#d9d9d9")
|
|
l_type.grid(row=0, column=0, **optsGrid_e)
|
|
self.dv_type = tk.StringVar()
|
|
self.dv_type.set(ecu['type'])
|
|
e_type = tk.Entry(self.ecudlg, textvariable=self.dv_type, width=10, **ent_style)
|
|
e_type.grid(row=0, column=1, **optsGrid)
|
|
|
|
l_name = tk.Label(self.ecudlg, text='Name:', background="#d9d9d9")
|
|
l_name.grid(row=1, column=0, **optsGrid_e)
|
|
self.dv_name = tk.StringVar()
|
|
self.dv_name.set(ecu['name'])
|
|
e_name = tk.Entry(self.ecudlg, textvariable=self.dv_name, width=10, **ent_style)
|
|
e_name.grid(row=1, column=1, **optsGrid)
|
|
|
|
l_xid = tk.Label(self.ecudlg, text='Xid:', background="#d9d9d9")
|
|
l_xid.grid(row=2, column=0, **optsGrid_e)
|
|
self.dv_xid = tk.StringVar()
|
|
self.dv_xid.set(ecu['xid'])
|
|
e_xid = tk.Entry(self.ecudlg, textvariable=self.dv_xid, width=10, **ent_style)
|
|
e_xid.grid(row=2, column=1, **optsGrid)
|
|
|
|
l_rid = tk.Label(self.ecudlg, text='Rid:', background="#d9d9d9")
|
|
l_rid.grid(row=3, column=0, **optsGrid_e)
|
|
self.dv_rid = tk.StringVar()
|
|
self.dv_rid.set(ecu['rid'])
|
|
e_rid = tk.Entry(self.ecudlg, textvariable=self.dv_rid, width=10, **ent_style)
|
|
e_rid.grid(row=3, column=1, **optsGrid)
|
|
|
|
l_addr = tk.Label(self.ecudlg, text='Functional address:', background="#d9d9d9")
|
|
l_addr.grid(row=4, column=0, **optsGrid_e)
|
|
self.dv_addr = tk.StringVar()
|
|
self.dv_addr.set(ecu['addr'])
|
|
e_addr = tk.Entry(self.ecudlg, textvariable=self.dv_addr, width=10, **ent_style)
|
|
e_addr.grid(row=4, column=1, **optsGrid)
|
|
|
|
l_iso = tk.Label(self.ecudlg, text='ISO address:', background="#d9d9d9")
|
|
l_iso.grid(row=5, column=0, **optsGrid_e)
|
|
self.dv_iso = tk.StringVar()
|
|
self.dv_iso.set(ecu['iso8'])
|
|
e_iso = tk.Entry(self.ecudlg, textvariable=self.dv_iso, width=10, **ent_style)
|
|
e_iso.grid(row=5, column=1, **optsGrid)
|
|
|
|
l_ses = tk.Label(self.ecudlg, text='Session open cmd:', background="#d9d9d9")
|
|
l_ses.grid(row=6, column=0, **optsGrid_e)
|
|
self.dv_ses = tk.StringVar()
|
|
self.dv_ses.set(ecu['ses'])
|
|
e_ses = tk.Entry(self.ecudlg, textvariable=self.dv_ses, width=10, **ent_style)
|
|
e_ses.grid(row=6, column=1, **optsGrid)
|
|
|
|
v_protList = ['ISO8', 'KWP-SLOW', 'KWP-FAST', 'CAN-250', 'CAN-500']
|
|
l_pro = tk.Label(self.ecudlg, text='BUS type:', background="#d9d9d9")
|
|
l_pro.grid(row=7, column=0, **optsGrid_e)
|
|
self.dv_pro = tk.StringVar()
|
|
self.dv_pro.set(ecu['prot'])
|
|
c_pro = tkinter.ttk.Combobox(self.ecudlg)
|
|
c_pro.configure(values=v_protList)
|
|
c_pro.configure(textvariable=self.dv_pro)
|
|
c_pro.configure(takefocus="")
|
|
c_pro.grid(row=7, column=1, **optsGrid)
|
|
|
|
self.getXmlListByProj()
|
|
l_xml = tk.Label(self.ecudlg, text='Recommended XML:', background="#d9d9d9")
|
|
l_xml.grid(row=8, column=0, **optsGrid_e)
|
|
self.dv_xml = tk.StringVar()
|
|
self.dv_xml.set(ecu['xml'])
|
|
c_xml = tkinter.ttk.Combobox(self.ecudlg, width=30)
|
|
c_xml.configure(values=self.v_xmlList)
|
|
c_xml.configure(textvariable=self.dv_xml)
|
|
c_xml.configure(takefocus="")
|
|
c_xml.grid(row=8, column=1, **optsGrid_w)
|
|
#b_xml = tk.Button(self.ecudlg, text="XML file", command=self.xmlBtnClick, **btn_style)
|
|
#b_xml.grid(row=8, column=2, **optsGrid)
|
|
|
|
allxmllist = []
|
|
for l in sorted(mod_db_manager.get_file_list_from_ddt('ecus/*')):
|
|
allxmllist.append( os.path.basename(l) )
|
|
l2_xml = tk.Label(self.ecudlg, text='ALL XML:', background="#d9d9d9")
|
|
l2_xml.grid(row=9, column=0, **optsGrid_e)
|
|
a_xml = tkinter.ttk.Combobox(self.ecudlg, width=30)
|
|
a_xml.configure(values=allxmllist)
|
|
a_xml.configure(textvariable=self.dv_xml)
|
|
a_xml.configure(takefocus="")
|
|
a_xml.grid(row=9, column=1, **optsGrid_w)
|
|
|
|
|
|
self.getDumpListByXml()
|
|
l_dump = tk.Label(self.ecudlg, text='Dump:', background="#d9d9d9")
|
|
l_dump.grid(row=10, column=0, **optsGrid_e)
|
|
self.dv_dump = tk.StringVar()
|
|
self.dv_dump.set(ecu['dump'])
|
|
c_dump = tkinter.ttk.Combobox(self.ecudlg, width=30)
|
|
c_dump.configure(values=self.v_dumpList)
|
|
c_dump.configure(textvariable=self.dv_dump)
|
|
c_dump.configure(takefocus="")
|
|
c_dump.grid(row=10, column=1, **optsGrid_w)
|
|
b_dump = tk.Button(self.ecudlg, text="Dump file", command=self.dumpBtnClick, **btn_style)
|
|
b_dump.grid(row=10, column=2, **optsGrid)
|
|
|
|
b_save = tk.Button(self.ecudlg, text="Save", command=self.ecuSaveBtnClick, **btn_style)
|
|
b_save.grid(row=11, column=1, **optsGrid)
|
|
|
|
b_canc = tk.Button(self.ecudlg, text="Cancel", command=self.ecuCancelBtnClick, **btn_style)
|
|
b_canc.grid(row=11, column=2, **optsGrid)
|
|
|
|
def renewEcuList(self):
|
|
self.ecutree.delete(*self.ecutree.get_children())
|
|
for ecu in mod_ddt_utils.multikeysort( self.carecus, ['undef','addr']):
|
|
columns = (ecu['iso8'], ecu['xid'], ecu['rid'], ecu['prot'], ecu['type'], ecu['name'], ecu['xml'], ecu['dump'], ecu)
|
|
if ecu['undef']=='0':
|
|
self.ecutree.insert('', 'end', text=ecu['addr'], values=columns, tag='t1')
|
|
else:
|
|
self.ecutree.insert('', 'end', text=ecu['addr'], values=columns, tag='')
|
|
self.ecutree.tag_configure('t1', background = "#fefcef")
|
|
self.ecutree.update()
|
|
|
|
def applySettings(self):
|
|
mod_globals.opt_port = self.var_port.get().split(';')[0]
|
|
mod_globals.opt_rate = int(self.var_speed.get())
|
|
mod_globals.opt_can2 = self.var_can2.get()
|
|
if self.var_log.get():
|
|
mod_globals.opt_log = self.var_logName.get()
|
|
else:
|
|
mod_globals.opt_log = ""
|
|
mod_globals.opt_cfc0 = True
|
|
|
|
def xmlBtnClick(self):
|
|
filename = tkinter.filedialog.askopenfilename(initialdir=mod_globals.ddtroot+'/ecus/', title='Select file',
|
|
filetypes=[('xml files', '*.xml')])
|
|
if '/' in filename:
|
|
xfn = filename.split('/')[-1]
|
|
else:
|
|
xfn = filename.split('\\')[-1]
|
|
self.dv_xml.set(xfn)
|
|
return
|
|
|
|
def dumpBtnClick(self):
|
|
filename = tkinter.filedialog.askopenfilename(initialdir='./dumps/', title='Select file',
|
|
filetypes=[('txt files', '*.txt')])
|
|
if '/' in filename:
|
|
xfn = filename.split('/')[-1]
|
|
else:
|
|
xfn = filename.split('\\')[-1]
|
|
self.dv_dump.set(xfn)
|
|
return
|
|
|
|
def ecuSaveBtnClick(self):
|
|
if self.currentEcu==None:
|
|
return
|
|
self.carecus[self.currentEcu]['type'] = self.dv_type.get()
|
|
self.carecus[self.currentEcu]['name'] = self.dv_name.get()
|
|
self.carecus[self.currentEcu]['xid'] = self.dv_xid.get()
|
|
self.carecus[self.currentEcu]['rid'] = self.dv_rid.get()
|
|
self.carecus[self.currentEcu]['addr'] = self.dv_addr.get()
|
|
self.carecus[self.currentEcu]['iso8'] = self.dv_iso.get()
|
|
self.carecus[self.currentEcu]['prot'] = self.dv_pro.get()
|
|
self.carecus[self.currentEcu]['ses'] = self.dv_ses.get()
|
|
self.carecus[self.currentEcu]['xml'] = self.dv_xml.get()
|
|
self.carecus[self.currentEcu]['dump'] = self.dv_dump.get()
|
|
if self.dv_xml.get()!='':
|
|
self.carecus[self.currentEcu]['undef'] = '0'
|
|
else:
|
|
self.carecus[self.currentEcu]['undef'] = '1'
|
|
self.ecudlg.destroy()
|
|
self.renewEcuList()
|
|
return
|
|
|
|
def ecuCancelBtnClick(self):
|
|
self.ecudlg.destroy()
|
|
return
|
|
|
|
def getXmlListByProj(self):
|
|
self.v_xmlList = []
|
|
try:
|
|
for t in self.eculist[self.dv_addr.get()]['targets']:
|
|
if self.v_proj.get().upper() in self.eculist[self.dv_addr.get()]['targets'][t]['Projects']:
|
|
self.v_xmlList.append(t)
|
|
except:
|
|
pass
|
|
|
|
def getDumpListByXml(self, xmlname=None):
|
|
|
|
if xmlname==None:
|
|
self.v_dumpList = []
|
|
xml = self.dv_xml.get()[:-4]
|
|
for root, dirs, files in os.walk("./dumps"):
|
|
for f in files:
|
|
if (xml + '.') in f:
|
|
self.v_dumpList.append(f)
|
|
else:
|
|
xmlname = xmlname[:-4]
|
|
flist = []
|
|
for root, dirs, files in os.walk("./dumps"):
|
|
for f in files:
|
|
if (xmlname + '.') in f:
|
|
flist.append(f)
|
|
|
|
if len(flist) == 0: return []
|
|
flist.sort()
|
|
return flist
|
|
|
|
def saveSettings(self):
|
|
self.save.port = self.var_port.get().split(';')[0]
|
|
self.save.speed = self.var_speed.get()
|
|
self.save.log = self.var_log.get()
|
|
self.save.logName = self.var_logName.get()
|
|
self.save.cfc = self.var_cfc.get()
|
|
self.save.dump = self.var_dump.get()
|
|
self.save.save()
|
|
|
|
def loadSettings(self):
|
|
|
|
self.var_cfc.set(self.save.cfc)
|
|
self.var_dump.set(self.save.dump)
|
|
self.var_port.set(self.save.port)
|
|
self.var_speed.set(self.save.speed)
|
|
self.var_log.set(self.save.log)
|
|
self.var_logName.set(self.save.logName)
|
|
|
|
self.var_speedList = ['38400', '115200', '230400', '500000', '1000000', '2000000' ]
|
|
self.var_portList = mod_ddt_utils.getPortList()
|
|
|
|
if len(self.var_port.get()) == 0:
|
|
for p in self.var_portList:
|
|
self.var_port.set(p)
|
|
if 'OBD' in p: break
|
|
|
|
def main():
|
|
'''Main function'''
|
|
|
|
mod_utils.chkDirTree()
|
|
mod_db_manager.find_DBs()
|
|
|
|
lau = DDTLauncher()
|
|
|
|
print("Done")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|