Python基於周立功ZCANPRO開發刷寫指令碼

2022-07-09 18:01:11

一、概述

1.背景

本文章主要是記錄用Python基於周立功ZCANPRO開發VIN和SN碼刷寫工具。

 

2.環境搭建

Python3.8.10 32位元(必須)

周立功上位機:ZCANPRO

周立功CAN盒:USBCANFD-200U

 

二、刷寫指令碼

from ctypes import *
import os, time
import zcanpro

"""
使用方法:
1.VIN填寫需要刷寫的VIN碼,如:VIN="12345678901234567"
2.SNN填寫需要刷寫的VIN碼,如:SN="12345678901234567890123456"
3.ZCANPRO工具擴充套件指令碼功能執行本指令碼
"""
VIN = ""  # 填寫VIN碼
SN = ""  # 填寫SN碼

stopTask = False


def z_notify(type, obj):
    zcanpro.write_log("Notify " + str(type) + " " + str(obj))
    if type == "stop":
        zcanpro.write_log("Stop...")
        global stopTask
        stopTask = True


def uds_req(buses, req):
    """診斷服務命令封裝"""
    zcanpro.write_log("[UDS Tx] " + ("%02X " % req["sid"]) + " ".join('{:02X}'.format(a) for a in req["data"]))
    response = zcanpro.uds_request(buses[0]["busID"], req)
    if not response["result"]:
        zcanpro.write_log("Request error! " + response["result_msg"])
    else:
        zcanpro.write_log("[UDS Rx] " + " ".join('{:02X}'.format(a) for a in response["data"]))
    return response


def uds_Serve(sid, data):
    """data組裝"""
    uds = {"src_addr": 0x113, "dst_addr": 0x11b, "suppress_response": 0, "sid": 0x10, "data": []}
    uds["sid"] = sid
    uds["data"] = data
    return uds


def z_main():
    udsCfg = {
        "response_timeout_ms": 3000,
        "use_canfd": 1,
        "canfd_brs": 1,
        "trans_ver": 0,
        "fill_byte": 0x00,
        "frame_type": 0,
        "trans_stmin_valid": 0,
        "trans_stmin": 0,
        "enhanced_timeout_ms": 5000
    }
    lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), 'DLL檔案'))  # 呼叫DLL解密檔案
    buses = zcanpro.get_buses()
    zcanpro.uds_init(udsCfg)

    def unlock_27():
        """處理27服務解鎖DLL方法"""
        uds_req(buses, uds_Serve(0x10, [0x03]))
        response1 = uds_req(buses, uds_Serve(0x27, [0x01]))
        if response1["data"][0] == 0x67:
            m = 0x00
            for i in range(2, len(response1["data"])):
                m = m | response1["data"][i] << 24 - 8 * (i - 2)
            lib.keyFromSeedLevel1.restype = c_ulong  # 定義DLL返回型別
            keys = lib.keyFromSeedLevel1(m)
            data_27 = [0x02]
            n1 = divmod(keys, 0x1000000)[0]
            n2 = divmod(divmod(keys, 0x10000)[0], 0x100)[1]
            n3 = divmod(divmod(keys, 0x10000)[1], 0x100)[0]
            n4 = divmod(keys, 0x100)[1]
            data_27.append(n1)
            data_27.append(n2)
            data_27.append(n3)
            data_27.append(n4)
            response2 = uds_req(buses, uds_Serve(0x27, data_27))
            if response2["data"][0] == 0x67:
                return True
            else:
                zcanpro.write_log('27解鎖失敗')
                return False
        return False

    if VIN != "":
        if len(VIN.strip()) == 17:
            """刷寫VIN碼"""
            if unlock_27():
                VIN_16hex = [ord(i) for i in VIN]
                data = [0xF1, 0x90] + VIN_16hex
                uds_req(buses, uds_Serve(0x2E, data))
                response3 = uds_req(buses, uds_Serve(0x22, [0xF1, 0x90]))
                if response3["data"][3:] == VIN_16hex:
                    zcanpro.write_log("VIN刷寫成功")
                else:
                    zcanpro.write_log("VIN刷寫失敗")
            else:
                zcanpro.write_log("27解鎖失敗")
        else:
            zcanpro.write_log("VIN碼長度不是17位")

    if SN != "":
        if len(SN.strip()) == 26:
            """刷寫SN碼"""
            if unlock_27():
                SN_16hex = [ord(i) for i in SN]
                write_31 = [0x01, 0xFF, 0xAA, 0x03, 0x04, 0x1A, 0x00] + SN_16hex
                CR = 0
                for i in range(3, len(write_31)):
                    CR = CR ^ write_31[i]
                write_31.append(CR)
                uds_req(buses, uds_Serve(0x31, write_31))
                response = uds_req(buses, uds_Serve(0x22, [0xF1, 0x8C]))
                if response['data'][3:] == SN_16hex:
                    zcanpro.write_log("SN刷寫成功")
                else:
                    zcanpro.write_log("SN刷寫失敗")
        else:
            zcanpro.write_log("SN碼長度不是26位")
    time.sleep(1)
    zcanpro.uds_deinit()

 

三、刷寫VIN與SN

1.開啟上位機ZCANPRO-高階功能-擴充套件指令碼

2.執行章節二的刷寫指令碼