Send multiple dataids in one data request

This commit is contained in:
Marianpol 2020-10-13 01:25:46 +02:00
parent f34a4f2733
commit a3213ce6e2
5 changed files with 100 additions and 6 deletions

View File

@ -150,6 +150,9 @@ class ECU:
self.elm.start_session( self.ecudata['startDiagReq'] )
if self.ecudata['pin'].lower()=='can' and self.DataIds:
self.elm.checkPerformaceLevel(self.DataIds)
print "Done"
global ecudump
@ -347,8 +350,9 @@ class ECU:
else:
initScreen = chr(27)+"[2J"+chr(27)+"[;H"
csvf = 0
self.elm.currentScreenDataIds = []
mask = False
masks = []
datarefsToRemove = []
@ -386,6 +390,7 @@ class ECU:
if mod_globals.opt_csv and mod_globals.ext_cur_DTC == '000000':
# prepare to csv save
self.minimumrefreshrate = 0
mod_globals.opt_perform = True
csvline = "sep=\\t\n"
csvline += u"Time"
nparams = 0
@ -527,6 +532,8 @@ class ECU:
time.sleep(tb + self.minimumrefreshrate - tc)
tb = tc
self.elm.currentScreenDataIds = self.getDataIds(self.elm.rsp_cache.keys(), self.DataIds)
if kb.kbhit():
c = kb.getch()
if len(c)!=1: continue
@ -1026,6 +1033,23 @@ class ECU:
map[key] = label
return map
def getDataIds(self, cache, dataids):
dataIdsList = []
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:]])
chunk_size = self.elm.performanceModeLevel
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)]
return dataIdsList
def bukva( bt, l, sign = False ):
S1 = chr((bt-l) % 26 + ord('A'))

View File

@ -58,8 +58,14 @@ def executeService( service, elm, status = [], param = "", cache = False ):
#tb = time.time() #start time
#tc = tb
sentDataIdentifires = [] #dataids sent in one 22 request, nedded for a response parse
performanceMode = mod_globals.opt_perform and elm.performanceModeLevel > 1
commandToSend = service.startReq
if performanceMode and elm.currentScreenDataIds:
commandToSend, sentDataIdentifires = prepareComplexRequest(service.startReq, elm.currentScreenDataIds)
if len(service.params)>0: # but I support only one and do not support SnapShot
if service.params[0]['type']=='DTC':
param = mod_globals.ext_cur_DTC
@ -78,6 +84,9 @@ def executeService( service, elm, status = [], param = "", cache = False ):
rsp = rspStrip( rsp, commandToSend )
first_rsp = rsp
if performanceMode and sentDataIdentifires:
first_rsp = parseComplexResponse(elm, service.simpleRsp, rsp, sentDataIdentifires)
#print "Status:", status
#print "Delay:",localDelay,
#print "startReq ", service.startReq
@ -151,6 +160,43 @@ def executeService( service, elm, status = [], param = "", cache = False ):
print "\nSomething went wrong. Counter reached maximum value.\n"
return ""
def prepareComplexRequest(request, screenDataIds):
commandToSend = request
sentDataIdentifires = []
screenDataIdsNumber = len(screenDataIds[0])
if screenDataIdsNumber > 1:
firstDataId = screenDataIds[0][0].id
if firstDataId == request[2:]:
commandToSend = request[:2]
for did in screenDataIds[0]:
commandToSend += did.id
sentDataIdentifires = screenDataIds.pop(0)
return commandToSend, sentDataIdentifires
def parseComplexResponse(elm, positiveRsp, response, sentDataIds):
first_rsp = ''
posInResp = 2
byteLength = 2
sentDataIdsLength = len(sentDataIds)
for i in range(sentDataIdsLength):
dataId = response[posInResp:posInResp + 2 * byteLength]
posInResp += 2 * byteLength
didDataLength = int(sentDataIds[i].dataBitLength)/8
didData = response[posInResp: posInResp + didDataLength * byteLength]
posInResp += didDataLength * byteLength
if i == 0:
first_rsp = positiveRsp + dataId + didData
resp = positiveRsp + dataId + didData
resp = ' '.join(a+b for a,b in zip(resp[::2], resp[1::2]))
elm.rsp_cache['22' + dataId] = resp
return first_rsp
class ecu_service:

View File

@ -12,6 +12,7 @@ import string
import threading
import socket
from datetime import datetime
from collections import OrderedDict
try:
import androidhelper as android
@ -517,6 +518,7 @@ class ELM:
lastCMDtime = 0 # time when last command was sent to bus
portTimeout = 5 # timeout of port (com or tcp)
elmTimeout = 0 # timeout set by ATST
performanceModeLevel = 1 # number of dataids, that can be sent in one 22 request
# error counters
error_frame = 0
@ -536,7 +538,8 @@ class ELM:
startSession = ""
lastinitrsp = ""
rsp_cache = {} # cashes responses for current screen
currentScreenDataIds = [] #dataids displayed on current screen
rsp_cache = OrderedDict() # cashes responses for current screen
l1_cache = {} # save number of frames in responces
notSupportedCommands = {} # save them to not slow down polling
ecudump = {} # for demo only. contains responses for all 21xx and 22xxxx requests
@ -620,7 +623,7 @@ class ELM:
""" Clear L2 cache before screen update
"""
#print 'Clearing L2 cache'
self.rsp_cache = {}
self.rsp_cache = OrderedDict()
# if not mod_globals.opt_demo:
# self.rsp_cache = {}
@ -1926,7 +1929,7 @@ 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_adapter ()
def init_iso(self):
@ -2006,6 +2009,24 @@ class ELM:
self.check_answer(self.cmd("81")) # start session
self.check_adapter ()
#check if ELM uderstand full Single Frame with desired response length
def checkPerformaceLevel(self, dataids):
performanceLevels = [3, 2]
for level in performanceLevels:
if len(dataids) >= level:
paramToSend = ''
frameLength = '{:02X}'.format(1 + level * 2)
for i in range(level):
paramToSend += dataids.keys()[i]
cmd = frameLength + '22' + paramToSend + '1'
resp = self.send_raw(cmd)
if not '?' in resp and resp[2:4] != '7F':
self.performanceModeLevel = level
return
def reset_elm(self):
self.cmd ("at z")

View File

@ -32,6 +32,7 @@ opt_can2 = False #can connected to pins 13 and 12
opt_ddtxml = ""
opt_stn = False
opt_sd = False #separate doc files
opt_perform = False
dumpName = ""

View File

@ -237,7 +237,9 @@ def optParser():
else:
print "Development MODE"
mod_globals.opt_dev = True
mod_globals.opt_devses = options.dev
mod_globals.opt_devses = options.dev
if mod_globals.os == 'android':
mod_globals.opt_perform = True
def main():
'''Main function'''