diff --git a/VW_Flash_GUI.py b/VW_Flash_GUI.py index 25a9a20..da5427b 100644 --- a/VW_Flash_GUI.py +++ b/VW_Flash_GUI.py @@ -151,10 +151,10 @@ def __init__(self, parent): "cal": "", "flashpack": "", "bins": "", - "logger": "", + "logger": "logs", "interface": "", "singlecsv": False, - "logmode": "3E", + "logmode": "22", "activitylevel": "INFO", } write_config(self.options) diff --git a/VW_Flash_GUI.spec b/VW_Flash_GUI.spec index e116126..35be049 100644 --- a/VW_Flash_GUI.spec +++ b/VW_Flash_GUI.spec @@ -7,7 +7,7 @@ block_cipher = None a = Analysis(['VW_Flash_GUI.py'], pathex=[], binaries=[], - datas=[('logging.conf', '.'), ('data', 'data'), ('docs', 'docs'), ('lib/lzss/lzss.exe','lib/lzss/.')], + datas=[('logging.conf', '.'), ('data', 'data'), ('docs', 'docs'), ('lib/lzss/lzss.exe','lib/lzss/.'),('logs/config.yaml', 'logs/.'),('logs/parameters.yaml','logs/.')], hiddenimports=[], hookspath=[], hooksconfig={}, diff --git a/lib/simos_hsl.py b/lib/simos_hsl.py index 1e87d76..e8c7d2f 100644 --- a/lib/simos_hsl.py +++ b/lib/simos_hsl.py @@ -330,6 +330,41 @@ def main(self, client=None, callback=None): "Created 3E identifier: " + str(results.hex()) ) + elif self.MODE == "HSL": + memoryOffset = 0xB001E700 + self.payload = {} + + self.payload[memoryOffset] = "" + + maxSize = 0x8F * 2 + + while len(self.three_3ParamList) != 0: + self.payload[memoryOffset] += self.three_3ParamList[0:2] + if len(self.payload[memoryOffset]) >= 0x8F * 2: + memoryOffset += 0x8F + self.payload[memoryOffset] = "" + self.three_3ParamList = self.three_3ParamList[2:] + + if len(self.three_3ParamList) == 0: + self.payload[memoryOffset] += "00" + + for request in self.payload: + fullRequest = ( + "3E02" + + str(hex(request)).lstrip("0x") + + str(hex(int(len(self.payload[request]) / 2))) + .lstrip("0x") + .zfill(4) + + self.payload[request] + ) + self.activityLogger.debug("sending HSL request to set up logging: ") + self.activityLogger.debug(fullRequest) + results = self.send_raw(bytes.fromhex(fullRequest)) + self.activityLogger.debug( + "Created HSL identifier: " + str(results.hex()) + ) + + elif self.MODE == "2C": self.activityLogger.debug("Opening extended diagnostic session...") client.change_session(0x4F) @@ -423,6 +458,8 @@ def getValuesFromECU(self): self.getParams23() elif self.MODE == "3E": self.getParams3E() + elif self.MODE == "HSL": + self.getParamsHSL() else: self.getParams22() if self.logFile: @@ -501,22 +538,160 @@ def getParams3E(self): self.dataStream = self.dataStreamBuffer - if "Cruise" in self.dataStream: - if self.dataStream["Cruise"]["value"] != "0.0": - self.activityLogger.debug("Cruise control logging enabled") - self.stopTime = None - self.datalogging = True - elif ( - self.dataStream["Cruise"]["value"] == "0.0" - and self.datalogging == True - and self.stopTime is None - ): - self.stopTime = datetime.now() + timedelta(seconds=5) - - if self.datalogging is False and self.logFile is not None: - self.activityLogger.debug("Datalogging stopped, closing file") - self.logFile.close() - self.logFile = None + # if "Cruise" in self.dataStream: + # if self.dataStream["Cruise"]["value"] != "0.0": + # self.activityLogger.debug("Cruise control logging enabled") + # self.stopTime = None + # self.datalogging = True + # elif ( + # self.dataStream["Cruise"]["value"] == "0.0" + # and self.datalogging == True + # and self.stopTime is None + # ): + # self.stopTime = datetime.now() + timedelta(seconds=5) + + # if self.datalogging is False and self.logFile is not None: + # self.activityLogger.debug("Datalogging stopped, closing file") + # self.logFile.close() + # self.logFile = None + + self.datalogging = True + self.stopTime = None + + if self.datalogging is True: + if self.logFile is None: + if "logprefix" in self.configuration: + if self.SINGLECSV: + self.filename = ( + self.FILEPATH + + self.configuration["logprefix"] + + "_Logging_" + + self.CURRENTTIME + + ".csv" + ) + else: + self.filename = ( + self.FILEPATH + + self.configuration["logprefix"] + + "_Logging_" + + datetime.now().strftime("%Y%m%d-%H%M%S") + + ".csv" + ) + else: + if self.SINGLECSV: + self.filename = ( + self.FILEPATH + + "Logging_" + + self.CURRENTTIME + + ".csv" + ) + else: + self.filename = ( + self.FILEPATH + + "Logging_" + + datetime.now().strftime("%Y%m%d-%H%M%S") + + ".csv" + ) + self.activityLogger.debug( + "Opening logfile at: " + self.filename + ) + self.logFile = open(self.filename, "a") + if not self.SINGLECSV: + self.logFile.write(self.csvHeader + "\n") + + self.logFile.write(row + "\n") + + def getParamsHSL(self): + for address in self.payload: + if address % 256 == 0: + self.activityLogger.debug("Sending request for: " + str(hex(address))) + + results = self.send_raw( + bytes.fromhex("3e04" + str(hex(address)).lstrip("0x") + "ffff") + + ) + + if results is not None: + results = results.hex() + else: + results = "No Response from ECU" + self.activityLogger.debug(str(results)) + + # Make sure the result starts with an affirmative + if results: + self.dataStreamBuffer = {} + + # Set the datetime for the beginning of the row + row = str(datetime.now().time()) + self.dataStreamBuffer["Time"] = { + "value": str(datetime.now().time()), + "raw": "", + } + self.dataStreamBuffer["datalogging"] = { + "value": str(self.datalogging), + "raw": "", + } + + # Strip off the first 6 characters (F200) so we only have the data + results = results[2:] + + # The data comes back as raw data, so we need the size of each variable and its + # factor so that we can actually parse it. In here, we'll pull X bytes off the + # front of the result, process it, add it to the CSV row, and then remove it from + # the result + for parameter in self.logParams: + val = results[: self.logParams[parameter]["length"] * 2] + self.activityLogger.debug( + str(parameter) + " raw from ecu: " + str(val) + ) + rawval = int.from_bytes( + bytearray.fromhex(val), + "little", + signed=self.logParams[parameter]["signed"], + ) + self.activityLogger.debug( + str(parameter) + " pre-function: " + str(rawval) + ) + val = round( + eval( + self.logParams[parameter]["function"], + {"x": rawval, "struct": struct}, + ), + 2, + ) + row += "," + str(val) + self.activityLogger.debug( + str(parameter) + " scaling applied: " + str(val) + ) + + results = results[self.logParams[parameter]["length"] * 2 :] + + self.dataStreamBuffer[parameter] = { + "value": str(val), + "raw": str(rawval), + } + + self.dataStream = self.dataStreamBuffer + + # if "Cruise" in self.dataStream: + # if self.dataStream["Cruise"]["value"] != "0.0": + # self.activityLogger.debug("Cruise control logging enabled") + # self.stopTime = None + # self.datalogging = True + # elif ( + # self.dataStream["Cruise"]["value"] == "0.0" + # and self.datalogging == True + # and self.stopTime is None + # ): + # self.stopTime = datetime.now() + timedelta(seconds=5) + + # if self.datalogging is False and self.logFile is not None: + # self.activityLogger.debug("Datalogging stopped, closing file") + # self.logFile.close() + # self.logFile = None + + self.datalogging = True + self.stopTime = None if self.datalogging is True: if self.logFile is None: @@ -560,6 +735,132 @@ def getParams3E(self): self.logFile.write(self.csvHeader + "\n") self.logFile.write(row + "\n") + + def getParams22(self): + global logParams + global datalogging + global HEADLESS + global filepath + global dataStream + global logFile + global stopTime + + self.activityLogger.debug("Getting values via 0x22") + + self.dataStreamBuffer = {} + # Set the datetime for the beginning of the row + row = str(datetime.now().time()) + self.dataStreamBuffer["Time"] = {"value": str(datetime.now().time()), "raw": ""} + self.dataStreamBuffer["datalogging"] = {"value": str(self.datalogging), "raw": ""} + + for parameter in self.logParams: + if self.TESTING is True: + fakeVal = round(random.random() * 100) + self.activityLogger.debug( + "Param String: " + "22" + self.logParams[parameter]["location"].lstrip("0x") + ) + results = ( + "62" + + self.logParams[param]["location"].lstrip("0x") + + str(hex(fakeVal)).lstrip("0x") + ) + else: + results = ( + ( + self.send_raw( + bytes.fromhex( + "22" + + self.logParams[parameter]["location"].lstrip("0x") + ) + ) + ) + .hex() + ) + # print(str(results)) + + if results.startswith("62"): + + # Strip off the first 6 characters (62MEMORYLOCATION) so we only have the data + results = results[6:] + + val = results[: self.logParams[parameter]["length"] * 2] + self.activityLogger.debug(str(parameter) + " raw from ecu: " + str(val)) + rawval = int.from_bytes(bytearray.fromhex(val), "big", signed=self.logParams[parameter]["signed"]) + #rawval = int(val, 16) + self.activityLogger.debug(str(parameter) + " pre-function: " + str(rawval)) + val = round( + eval(self.logParams[parameter]["function"], {"x": rawval, "struct": struct}), + 2, + ) + row += "," + str(val) + self.activityLogger.debug(str(parameter) + " scaling applied: " + str(val)) + + self.dataStreamBuffer[parameter] = {"value": str(val), "raw": str(rawval)} + + self.dataStream = self.dataStreamBuffer + + # if "Cruise" in self.dataStream: + # if self.dataStream["Cruise"]["value"] != "0.0": + # self.activityLogger.debug("Cruise control logging enabled") + # self.stopTime = None + # self.datalogging = True + # elif ( + # self.dataStream["Cruise"]["value"] == "0.0" + # and self.datalogging == True + # and self.stopTime is None + # ): + # self.stopTime = datetime.now() + timedelta(seconds=5) + + # if self.datalogging is False and self.logFile is not None: + # self.activityLogger.debug("Datalogging stopped, closing file") + # self.logFile.close() + # self.logFile = None + + self.datalogging = True + self.stopTime = None + + if self.datalogging is True: + if self.logFile is None: + if "logprefix" in self.configuration: + if self.SINGLECSV: + self.filename = ( + self.FILEPATH + + self.configuration["logprefix"] + + "_Logging_" + + self.CURRENTTIME + + ".csv" + ) + else: + self.filename = ( + self.FILEPATH + + self.configuration["logprefix"] + + "_Logging_" + + datetime.now().strftime("%Y%m%d-%H%M%S") + + ".csv" + ) + else: + if self.SINGLECSV: + self.filename = ( + self.FILEPATH + + "Logging_" + + self.CURRENTTIME + + ".csv" + ) + else: + self.filename = ( + self.FILEPATH + + "Logging_" + + datetime.now().strftime("%Y%m%d-%H%M%S") + + ".csv" + ) + self.activityLogger.debug( + "Opening logfile at: " + self.filename + ) + self.logFile = open(self.filename, "a") + if not self.SINGLECSV: + self.logFile.write(self.csvHeader + "\n") + + self.logFile.write(row + "\n") def getParams2C(self): @@ -638,22 +939,25 @@ def getParams2C(self): self.dataStream = self.dataStreamBuffer - if "Cruise" in self.dataStream: - if self.dataStream["Cruise"]["value"] != "0.0": - self.activityLogger.debug("Cruise control logging enabled") - self.stopTime = None - self.datalogging = True - elif ( - self.dataStream["Cruise"]["value"] == "0.0" - and self.datalogging == True - and self.stopTime is None - ): - self.stopTime = datetime.now() + timedelta(seconds=5) - - if self.datalogging is False and self.logFile is not None: - self.activityLogger.debug("Datalogging stopped, closing file") - self.logFile.close() - self.logFile = None + # if "Cruise" in self.dataStream: + # if self.dataStream["Cruise"]["value"] != "0.0": + # self.activityLogger.debug("Cruise control logging enabled") + # self.stopTime = None + # self.datalogging = True + # elif ( + # self.dataStream["Cruise"]["value"] == "0.0" + # and self.datalogging == True + # and self.stopTime is None + # ): + # self.stopTime = datetime.now() + timedelta(seconds=5) + + # if self.datalogging is False and self.logFile is not None: + # self.activityLogger.debug("Datalogging stopped, closing file") + # self.logFile.close() + # self.logFile = None + + self.datalogging = True + self.stopTime = None if self.datalogging is True: if self.logFile is None: @@ -795,116 +1099,6 @@ def stream_data(callback=None): activityLogger.info("socket closed due to error or client disconnect") -# Read from the ECU using mode 22 -def getParams22(): - global logParams - global datalogging - global HEADLESS - global filepath - global dataStream - global logFile - global stopTime - - activityLogger.debug("Getting values via 0x22") - - dataStreamBuffer = {} - # Set the datetime for the beginning of the row - row = str(datetime.now().time()) - dataStreamBuffer["Time"] = {"value": str(datetime.now().time()), "raw": ""} - dataStreamBuffer["datalogging"] = {"value": str(datalogging), "raw": ""} - - for parameter in logParams: - if TESTING is True: - fakeVal = round(random.random() * 100) - activityLogger.debug( - "Param String: " + "22" + logParams[parameter]["location"].lstrip("0x") - ) - results = ( - "62" - + logParams[param]["location"].lstrip("0x") - + str(hex(fakeVal)).lstrip("0x") - ) - else: - results = ( - ( - send_raw_2( - bytes.fromhex( - "0322" - + logParams[parameter]["location"].lstrip("0x") - + "00000000" - ) - ) - ) - .hex() - .rstrip("a") - ) - # print(str(results)) - - if results.startswith("0562"): - - # Strip off the first 6 characters (63MEMORYLOCATION) so we only have the data - results = results[8:] - - val = results[: logParams[parameter]["length"] * 2] - activityLogger.debug(str(parameter) + " raw from ecu: " + str(val)) - # rawval = int.from_bytes(bytearray.fromhex(val),'little', signed=logParams[parameter]['signed']) - rawval = int(val, 16) - activityLogger.debug(str(parameter) + " pre-function: " + str(rawval)) - val = round( - eval(logParams[parameter]["function"], {"x": rawval, "struct": struct}), - 2, - ) - row += "," + str(val) - activityLogger.debug(str(parameter) + " scaling applied: " + str(val)) - - dataStreamBuffer[parameter] = {"value": str(val), "raw": str(rawval)} - - dataStream = dataStreamBuffer - - if "Cruise" in dataStream: - if dataStream["Cruise"]["value"] != "0.0": - activityLogger.debug("Cruise control logging enabled") - stopTime = None - datalogging = True - elif ( - dataStream["Cruise"]["value"] == "0.0" - and datalogging == True - and stopTime is None - ): - stopTime = datetime.now() + timedelta(seconds=5) - - if datalogging is False and logFile is not None: - activityLogger.debug("Datalogging stopped, closing file") - logFile.close() - logFile = None - - if datalogging is True: - if logFile is None: - if "logprefix" in configuration: - filename = ( - filepath - + configuration["logprefix"] - + "_Logging_" - + datetime.now().strftime("%Y%m%d-%H%M%S") - + ".csv" - ) - else: - filename = ( - filepath - + "Logging_" - + datetime.now().strftime("%Y%m%d-%H%M%S") - + ".csv" - ) - - activityLogger.debug("Creating new logfile at: " + filename) - activityLogger.debug("Header for CSV file: " + csvHeader) - logFile = open(filename, "a") - logFile.write(csvHeader + "\n") - activityLogger.debug(row) - logFile.write(row + "\n") - logFile.flush() - - # Read from the ECU using mode 23 def getParams23(): global logParams diff --git a/logs/config.yaml b/logs/config.yaml new file mode 100644 index 0000000..5b53b5e --- /dev/null +++ b/logs/config.yaml @@ -0,0 +1,8 @@ +snotification: + smtp_port: 465 + smtp_server: smtp.gmail.com + from: fromaddress@gmail.com + to: toaddress@gmail.com + password: somepassword + +logprefix: "VWFlash" diff --git a/logs/parameters.yaml b/logs/parameters.yaml new file mode 100644 index 0000000..9cf52f5 --- /dev/null +++ b/logs/parameters.yaml @@ -0,0 +1,175 @@ +Cruise: + length: 0x02 + signed: False + function: "x" + units: "-" + location: '0x203c' + +Ambient Pressure: + length: 0x02 + signed: False + function: "x/120.6017666543982" + units: "kPa" + location: '0x13ca' + +Engine Speed: + length: 0x02 + signed: False + function: "x/4" + units: "RPM" + location: '0xf40c' + +IAT: + length: 0x01 + signed: False + function: "x*0.75-48" + units: "*C" + location: '0x1001' + +MAP: + length: 0x02 + signed: False + function: "x/10" + units: "kPa" + location: '0x39c0' + +TPS: + length: 0x02 + signed: True + function: "x/10" + units: "%" + location: '0x20ba' + +AFR: + length: 0x02 + signed: False + function: "x/69.6598639456" + units: "AFR" + location: '0x10c0' + +AFR SP: + length: 0x02 + signed: False + function: "x/2229.11564626" + units: "AFR_SP" + location: '0xf444' + +Airmass: + length: 0x02 + signed: False + function: "x/47.181" + units: "mg/stk" + location: '0x13d9' + +Current Gear: + length: 0x02 + signed: False + function: "x+1" + units: "" + location: '0x210f' + +FP DI: + length: 0x02 + signed: False + function: "x/10" + units: "bar" + location: '0x2027' + +FP DI SP: + length: 0x02 + signed: False + function: "x/10" + units: "bar" + location: '0x293b' + +FP MPI: + length: 0x02 + signed: False + function: "x/1000" + units: "bar" + location: '0x2025' + +FP MPI SP: + length: 0x02 + signed: False + function: "x/1000" + units: "bar" + location: '0x2932' + +Ign Timing Avg: + length: 0x02 + signed: True + function: "x/100" + units: "KW" + location: '0x2004' + +Knock Cyl 1: + length: 0x02 + signed: True + function: "x/100" + units: "KW" + location: '0x200a' + +Knock Cyl 2: + length: 0x02 + signed: True + function: "x/100" + units: "KW" + location: '0x200b' + +Knock Cyl 3: + length: 0x02 + signed: True + function: "x/100" + units: "KW" + location: '0x200c' + +Knock Cyl 4: + length: 0x02 + signed: True + function: "x/100" + units: "KW" + location: '0x200d' + +PUT: + length: 0x02 + signed: False + function: "x/10" + units: "kPa" + location: '0x202a' + +PUT SP: + length: 0x02 + signed: False + function: "x/10" + units: "kPa" + location: '0x2029' + +Torque: + length: 0x02 + signed: True + function: "x/10" + units: "Nm" + location: '0x437c' + +Torque Req: + length: 0x02 + signed: True + function: "x/10" + units: "Nm" + location: '0x4380' + +Wastegate: + length: 0x02 + signed: False + function: "100-x/100" + units: "%" + location: '0x39a2' + +Turbo Speed: + length: 0x02 + signed: False + function: "x/163.8400000001536" + units: "krpm" + location: '0x1040' + diff --git a/setup.py b/setup.py index 471292a..851c558 100644 --- a/setup.py +++ b/setup.py @@ -9,6 +9,7 @@ "data", ["data/box_codes.csv", "data/mqb_dsg_key.bin", "data/dtcs.csv", "data/frf.key"], ), + ("logs", ["logs/config.yaml", "logs/parameters.yaml"]), ] setup(console=["VW_Flash_GUI.py"], data_files=data_files)