From 0b4be10a8c587d222de7f58f17da3f25b641e72d Mon Sep 17 00:00:00 2001 From: Marianpol Date: Sun, 28 Aug 2022 12:50:22 +0200 Subject: [PATCH] Check performance level fixes One function for all levels Predict multiple did response length --- pyren/mod_elm.py | 90 +++++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 43 deletions(-) diff --git a/pyren/mod_elm.py b/pyren/mod_elm.py index 8fcce3b..d6f349f 100644 --- a/pyren/mod_elm.py +++ b/pyren/mod_elm.py @@ -2154,67 +2154,71 @@ class ELM: performanceLevels = [3, 2] for level in performanceLevels: - isLevelAccepted = self.checkPerformaceLevel(level, dataids) - if isLevelAccepted: + is_level_accepted = self.check_performance_level(level, dataids) + if is_level_accepted: break if self.performanceModeLevel == 3 and mod_globals.opt_obdlink: - for level in reversed(range(4,100)): #26 - 1 = 25 parameters per page - isLevelAccepted = self.checkPerformaceLevel(level, dataids) - if isLevelAccepted: + for level in reversed(range(4, 100)): # (number_of_dids_to_get_multiframe_request, max_performance_level_to_check - 1) + is_level_accepted = self.check_performance_level(level, dataids) + if is_level_accepted: return - def checkPerformaceLevel(self, level, dataids): + def check_performance_level(self, level, dataids): if len(dataids) >= level: - paramToSend = '' + predicted_response_length = 2 # length of string ReadDataByIdentifier service byte - 0x22 + did_number = 0 + param_to_send = '' - if level <= 3: # 3 dataids max can be send in single frame - frameLength = '{:02X}'.format(1 + level * 2) - for lvl in range(level): - paramToSend += dataids.keys()[lvl] - - cmd = '22' + paramToSend - - resp = self.cmd(cmd).replace(" ", "") #check response length first - if not all (c in string.hexdigits for c in resp): - return False - - if self.l1_cache.get(cmd, ""): - if mod_globals.opt_caf: - resp = self.send_raw(cmd + self.l1_cache.get(cmd)) # get all frames, not only first one - else: # prevents from triggering false error_frame error - resp = self.send_raw(frameLength + cmd + self.l1_cache.get(cmd)) - for s in resp.split('\n'): - if s.strip().startswith("037F") or "?" in s: - return False - - else: # send multiframe command for more than 3 dataids + if level > 3: # Send multiframe command for more than 3 dataids # Some modules can return NO DATA if multi frame command is sent after some no activity time # Sending anything before main command usually helps that command to be accepted self.send_cmd ("22" + dataids.keys()[0] + "1") - for lvl in range(level): - resp = self.request("22" + dataids.keys()[lvl]) - if any(s in resp for s in ['?', 'NR']): - continue - paramToSend += dataids.keys()[lvl] - cmd = '22' + paramToSend - resp = self.send_cmd(cmd) - if any(s in resp for s in ['?', 'NR']): + # while there is some dataids left and actual number of used dids + # is lower than requeseted performance level + while did_number < len(dataids) and len(param_to_send)/4 < level: + # get another did + did = dataids.keys()[did_number] + did_number += 1 + + # exclude did_supported_in_range did + # sent seperatly - response provided + # sent in multi did request - empty response + # these are available only in injection module + if not int('0x' + did, 16) % 0x20 and self.currentaddress == '7A': + continue + + #check if it is supported + resp = self.request("22" + did) + if not any(s in resp for s in ['?', 'NR']): + # add it to the list + param_to_send += did + predicted_response_length += len(did) + int(dataids[did].dataBitLength)/4 + + # if module does not support any did, we cannot check performance level + if not param_to_send: return False - - self.performanceModeLevel = level - return True + + cmd = '22' + param_to_send + resp = self.send_cmd(cmd).replace(" ", "") #check response length first + if any(s in resp for s in ['?', 'NR']) or len(resp) < predicted_response_length: + return False + + self.performanceModeLevel = len(param_to_send)/4 + return True + else: + return False def getRefreshRate(self): - refreshRate = 0 + refresh_rate = 0 if not self.screenRefreshTime: - return refreshRate + return refresh_rate - refreshRate = 1 / self.screenRefreshTime + refresh_rate = 1 / self.screenRefreshTime self.screenRefreshTime = 0 - return refreshRate + return refresh_rate def reset_elm(self): self.cmd ("at z")