From 04e089591c247506e777ba730e92d26b1a1aec38 Mon Sep 17 00:00:00 2001 From: Marianpol Date: Wed, 17 Feb 2021 22:14:38 +0100 Subject: [PATCH] csv_only mode upgrade --- pyren/mod_ecu.py | 133 ++++++++++++++++++++++++++----------- pyren/mod_ecu_parameter.py | 3 +- pyren/mod_ecu_state.py | 2 +- pyren/mod_elm.py | 42 ++++-------- pyren/pyren.py | 1 + 5 files changed, 113 insertions(+), 68 deletions(-) diff --git a/pyren/mod_ecu.py b/pyren/mod_ecu.py index f3b0208..133625a 100755 --- a/pyren/mod_ecu.py +++ b/pyren/mod_ecu.py @@ -398,11 +398,10 @@ class ECU: nparams = 0 for dr in datarefs: if dr.type=='State': - csvline += ";" + self.States[dr.name].codeMR + (":" + self.States[dr.name].label if mod_globals.opt_csv_human else "") + csvline += ";" + self.States[dr.name].codeMR + ":" + self.States[dr.name].label nparams += 1 if dr.type=='Parameter': - csvline += (";" + self.Parameters[dr.name].codeMR + (":" +self.Parameters[dr.name].label if mod_globals.opt_csv_human else "") + - " [" + self.Parameters[dr.name].unit + "]") + csvline += (";" + self.Parameters[dr.name].codeMR + ":" +self.Parameters[dr.name].label + " [" + self.Parameters[dr.name].unit + "]") nparams += 1 if mod_globals.opt_usrkey: csvline += ";User events" csvline = pyren_encode(csvline) @@ -434,25 +433,37 @@ class ECU: if len(datarefs)==0 and 'DE' not in path: return self.elm.clear_cache() - tmpArray = OrderedDict() + + #csv_only mode workflow in performance mode + #1. Read all parameters from the current screen using defalut mode + #2. Get all dataIds from the 22 service requests and create a list from them according to a module performance level + #3. Collect all 21 service requests and push them into requests list + #4. Create a complex requests from the all dataIds list and push them into requests list + #5. Send reqests from the requests list and save the responses in a responseHistory list + #6. On exit generate csv log file from the responseHistory - if mod_globals.opt_csv and mod_globals.opt_csv_only: + if mod_globals.opt_csv_only: print "Data is sending directly to csv-file" print "" print "Press any key to exit" page = 0 + + displayedDataIds = [] #Current screen dataIds list for csv_only mode + responseHistory = OrderedDict() + requests = OrderedDict() #list of requests to send in csv_only mode while(True): strlst = [] + datarefsRequestTime = int(round(time.time() * 1000)) - if mod_globals.opt_csv and csvf!=0: + if mod_globals.opt_csv_human and csvf!=0: csvline = csvline + "\n" #csvline = csvline.replace('.',',') #csvline = csvline.replace(',','.') csvline = csvline.replace(';','\t') - csvf.write(pyren_decode(csvline).encode('utf8') if mod_globals.opt_csv_human else csvline) + csvf.write(pyren_decode(csvline).encode('utf8')) #if mod_globals.os == 'nt' or mod_globals.os == 'android': # csvf.write(pyren_decode(csvline).encode('cp1251') if mod_globals.opt_csv_human else csvline) #else: @@ -460,16 +471,14 @@ class ECU: csvf.flush() csvline = datetime.now().strftime("%H:%M:%S.%f") - if mod_globals.opt_perform: - if not tmpArray or tmpArray.keys()[-1].startswith('21') : - for x in self.elm.rsp_cache.keys(): - if (x.startswith('22') and len(x) > 6) or x.startswith('21') or len(self.elm.rsp_cache) == 1: - tmpArray[x] = x - if len(self.elm.currentScreenDataIds) > 1: - tmpArray["22" + self.elm.currentScreenDataIds[-1][0].id] = "22" + self.elm.currentScreenDataIds[-1][0].id + #Collect all the requests from the current screen + if mod_globals.opt_perform and self.elm.performanceModeLevel > 1 and mod_globals.opt_csv_only: + if self.elm.rsp_cache: + if not requests: + requests = self.generateRequestsList() self.elm.clear_cache() - if not (tmpArray and mod_globals.opt_csv_only): + if not (mod_globals.opt_csv_only and requests): for dr in datarefs: datastr = dr.name help = dr.type @@ -490,8 +499,8 @@ class ECU: if dr.type=="Text": datastr = dr.name help = "" - if mod_globals.opt_csv and csvf!=0 and (dr.type=='State' or dr.type=='Parameter'): - csvline += ";" + (pyren_encode(csvd) if mod_globals.opt_csv_human else str(csvd)) + if mod_globals.opt_csv_human and csvf!=0 and (dr.type=='State' or dr.type=='Parameter'): + csvline += ";" + pyren_encode(csvd) if not (mod_globals.opt_csv and mod_globals.opt_csv_only): strlst.append(datastr) @@ -510,8 +519,8 @@ class ECU: strlst.append('\t'+line[i*W:(i+1)*W]) i=i+1 strlst.append('') - else: - for req in tmpArray: + else: #Send requests, do not calculate data + for req in requests: self.elm.request(req) if not (mod_globals.opt_csv and mod_globals.opt_csv_only): @@ -548,8 +557,13 @@ class ECU: time.sleep(tb + self.minimumrefreshrate - tc) tb = tc - if mod_globals.opt_perform: - self.elm.currentScreenDataIds = self.getDataIds(self.elm.rsp_cache.keys(), self.DataIds) + if mod_globals.opt_csv_only: + responseHistory[datarefsRequestTime] = self.elm.rsp_cache #Collect data to generate a file + + if mod_globals.opt_perform and self.elm.performanceModeLevel > 1: + self.elm.currentScreenDataIds = self.getDataIds(self.elm.rsp_cache, self.DataIds) + if self.elm.currentScreenDataIds: #DataIds list is generated only at first data read pass in csv_only mode + displayedDataIds = self.elm.currentScreenDataIds #We save it for file generating function if kb.kbhit(): c = kb.getch() @@ -565,8 +579,11 @@ class ECU: continue kb.set_normal_term() if mod_globals.opt_csv and csvf!=0: - csvf.close() - self.saveFavList() + self.saveFavList() + if mod_globals.opt_csv_human: + csvf.close() + return + self.createFile(responseHistory, displayedDataIds, csvline, csvf, datarefs) return else: n = ord(c)-ord('0') @@ -592,19 +609,58 @@ class ECU: continue kb.set_normal_term() if mod_globals.opt_csv and csvf!=0: - csvf.close() - # self.elm.vf.read() - # with open ("./logs/ecu_" + mod_globals.opt_log, "r") as f: - # for line in f: - # print line - for line in self.elm.vf: - print line - raw_input() - # raw_input('2322232') - # self.elm.vf.read() + if mod_globals.opt_csv_human: + csvf.close() + return + self.createFile(responseHistory, displayedDataIds, csvline, csvf, datarefs) if "DTC" in path: mod_globals.ext_cur_DTC = "000000" return + + def generateRequestsList(self): + requests = OrderedDict() + + currentScreenDataIdsLength = len(self.elm.currentScreenDataIds) + for reqDidsIndex in range(currentScreenDataIdsLength): #Create complex requests from all 22 requests + firstRequest = '22' + self.elm.currentScreenDataIds[0][0].id + complexRequest, sentDataIdentifires = prepareComplexRequest(firstRequest, self.elm.currentScreenDataIds) + requests[complexRequest] = complexRequest + for req in self.elm.rsp_cache.keys(): #Get all the 21 requests + if req.startswith('21'): + requests[req] = req + + return requests + + def createFile(self, responseHistory, displayedDataIds, csvline, csvf, datarefs): + clearScreen() + print 'Generating a file. Please wait...' + + for reqTime, reqCache in responseHistory.iteritems(): + for req, rsp in reqCache.iteritems(): + if req.startswith('22') and len(req) > 6: + for reqDids in displayedDataIds: + if reqDids[0].id == req[2:6]: + parseComplexResponse(self.elm, '62', rsp.replace(' ', ''), reqDids) + else: + self.elm.rsp_cache[req] = rsp + + csvline = csvline + "\n" + csvline = csvline.replace(';','\t') + csvf.write(pyren_decode(csvline).encode('utf8')) + csvf.flush() + csvline = datetime.fromtimestamp(reqTime/1000.0).strftime("%H:%M:%S.%f")[:-3] + + for dr in datarefs: + datastr = dr.name + help = dr.type + if dr.type=='State': + datastr, help, csvd = get_state( self.States[dr.name], self.Mnemonics, self.Services, self.elm, self.calc ) + if dr.type=='Parameter': + datastr, help, csvd = get_parameter( self.Parameters[dr.name], self.Mnemonics, self.Services, self.elm, self.calc ) + if csvf!=0 and (dr.type=='State' or dr.type=='Parameter'): + csvline += ";" + pyren_encode(csvd) + + csvf.close() def add_favourite(self): H = 25 @@ -1066,13 +1122,14 @@ class ECU: if self.elm.performanceModeLevel == 1: return dataIdsList - for key in cache: - if key.startswith('22'): - if key[2:] in dataids.keys(): - dataIdsList.append(dataids[key[2:]]) + for req in cache: + if req.startswith('22'): + if req[2:] in dataids.keys(): + if req not in self.elm.notSupportedCommands: + dataIdsList.append(dataids[req[2:]]) chunk_size = self.elm.performanceModeLevel - if dataIdsList: + if dataIdsList: # split dataIdsList into chunks based on the performace level return [dataIdsList[offset:offset+chunk_size] for offset in range(0, len(dataIdsList), chunk_size)] diff --git a/pyren/mod_ecu_parameter.py b/pyren/mod_ecu_parameter.py index b518082..1aadba8 100755 --- a/pyren/mod_ecu_parameter.py +++ b/pyren/mod_ecu_parameter.py @@ -31,9 +31,10 @@ def get_parameter( pr, mn, se, elm, calc, dataids = {} ): comp = comp.replace(m, val) pr.value = calc.calculate(comp) - csv_data = unicode(pr.value) if mod_globals.opt_csv_human else pr.value + if '.' in str(pr.value): pr.value = "%10.2f"%float(pr.value) + csv_data = unicode(pr.value) tmpmin = str(pr.min) tmpmax = str(pr.max) diff --git a/pyren/mod_ecu_state.py b/pyren/mod_ecu_state.py index 3688328..53e1e0d 100755 --- a/pyren/mod_ecu_state.py +++ b/pyren/mod_ecu_state.py @@ -23,7 +23,7 @@ def get_state( st, mn, se, elm, calc, dataids = {} ): else: st.value = str(tmp_val).encode("utf-8") - csv_val = unicode(st.value) if mod_globals.opt_csv_human else tmp_val + csv_val = unicode(st.value) if mod_globals.os=='android': st.value = " "*(8-len(st.value)/2) + st.value return "%-6s %-41s %-16s"%(st.codeMR,st.label,st.value), st.helps, csv_val diff --git a/pyren/mod_elm.py b/pyren/mod_elm.py index 6a3f62e..57497db 100644 --- a/pyren/mod_elm.py +++ b/pyren/mod_elm.py @@ -575,7 +575,7 @@ class ELM: if len(mod_globals.opt_log)>0: # and mod_globals.opt_demo==False: self.lf = open ("./logs/elm_" + mod_globals.opt_log, "at") - self.vf = open ("./logs/ecu_" + mod_globals.opt_log, "at+") + self.vf = open ("./logs/ecu_" + mod_globals.opt_log, "at") if mod_globals.opt_debug and mod_globals.debug_file==None: mod_globals.debug_file = open ("./logs/debug.txt", "at") @@ -602,7 +602,7 @@ class ELM: if mod_globals.opt_csv and not mod_globals.opt_demo: if mod_globals.opt_obdlink: self.port.soft_boudrate(2000000) - else: + elif self.port.portType == 0: self.port.soft_boudrate(230400) def __del__(self): @@ -1205,9 +1205,8 @@ class ELM: cmd_len = len (command) / 2 if cmd_len < 8: # single frame # check L1 cache here - # if isCommandInCache and int('0x' + self.l1_cache[commandString], 16) < 16: - if isCommandInCache: - raw_command.append ("STPX D:" + ("%0.2X" % cmd_len) + command + ",R:" +self.l1_cache[command]) + if isCommandInCache and int('0x' + self.l1_cache[commandString], 16) < 16: + raw_command.append (("%0.2X" % cmd_len) + command + self.l1_cache[command]) else: raw_command.append (("%0.2X" % cmd_len) + command) else: @@ -1224,20 +1223,12 @@ class ELM: # add response frames number to each frame to increase polling if mod_globals.opt_obdlink and mod_globals.opt_perform: if commandString[:2] in AllowedList and isCommandInCache: - readyFrame = '' - for f in raw_command: - readyFrame += f - raw_command = ["STPX D:" + readyFrame + ",R:" + self.l1_cache[commandString]] - - # if int('0x' + self.l1_cache[commandString], 16) < 16: - # for index in range(len(raw_command) - 1): - # raw_command[index] = raw_command[index] + '1' - # raw_command[-1] = raw_command[-1] + self.l1_cache[commandString] - # else: - # readyFrame = '' - # for f in raw_command: - # readyFrame += f - # raw_command = ["STPX D:" + readyFrame + ",R:" + self.l1_cache[commandString]] + for index in range(len(raw_command) - 1): + raw_command[index] = raw_command[index] + '1' + if int('0x' + self.l1_cache[commandString], 16) < 16: + raw_command[-1] = raw_command[-1] + self.l1_cache[commandString] + else: + raw_command[-1] = "STPX D:" + raw_command[-1] + ",R:" + self.l1_cache[commandString] responses = [] @@ -1307,10 +1298,10 @@ class ELM: # populate L1 cache if noerrors and commandString[:2] in AllowedList and not mod_globals.opt_n1c: - # if nframes < 16: - # self.l1_cache[commandString] = str(hex(nframes))[2:].upper() - # else: #for OBDLink STPX command - self.l1_cache[commandString] = str(nframes) + if nframes < 16: + self.l1_cache[commandString] = str(hex(nframes))[2:].upper() + else: #for OBDLink STPX command + self.l1_cache[commandString] = str(nframes) if len (result) / 2 >= nbytes and noerrors: # split by bytes and return @@ -1968,11 +1959,6 @@ class ELM: self.check_answer (self.cmd ("at at 1")) # reset adaptive timing step 3 self.check_answer (self.cmd ("at cra " + RXa)) - - self.check_answer (self.cmd ("at sh 35C")) - self.send_raw ("FA 40 00 00 00 20 60 04") - self.check_answer (self.cmd ("at sh " + TXa)) - self.check_adapter () def init_iso(self): diff --git a/pyren/pyren.py b/pyren/pyren.py index 56a25d2..6bb7b5c 100755 --- a/pyren/pyren.py +++ b/pyren/pyren.py @@ -219,6 +219,7 @@ def optParser(): mod_globals.opt_scan = options.scan mod_globals.opt_csv = options.csv mod_globals.opt_csv_only = options.csv_only + if mod_globals.opt_csv : mod_globals.opt_csv_human = True if mod_globals.opt_csv_only : mod_globals.opt_csv = True mod_globals.opt_csv_human = options.csv_human if mod_globals.opt_csv_human : mod_globals.opt_csv = True