在汽车电子产线、服务站或实验室中,你是否也遇到过这些痛点:刷写过程不可见、状态无法实时回传、失败后难以快速定位、无法与MES系统高效集成?
基于同星TSMaster软件平台与配套硬件的自动化刷写与流程状态实时显示方案,该方案通过 COM/RPC 自动化接口调用诊断系统变量,实现无人值守自动化刷写,并借助UDP实时通信将诊断流程步骤、执行状态、进度信息与刷写结果同步外发,支持命令行日志输出与图形化进度条可视化。
本文关键词:
自动化刷写、UDS诊断、COM自动化、RPC远程控制、UDP实时通信、流程状态回传、进度条可视化、配置防呆
01.方案亮点速览
🔹 配置防呆校验
自动检测工程路径、刷写文件合法性,异常即时提示,避免无效执行。
🔹 命令行实时状态显示
支持 bat/exe格式一键调用,命令行实时输出刷写流程与执行结果,步骤异常显示 Fail 并保留工程界面。
🔹 进度条可视化
独立弹窗置顶显示刷写进度:初始化、刷写中、刷写完成三级进度提示,百分比实时刷新,直观展示执行进度。
🔹 异常处理(可选)
刷写成功自动退出工程,刷写失败保留工程界面并抛出错误,便于问题定位。
02.典型应用场景
本方案主要面向多数汽车电子产线和主机厂、整车厂服务站、零部件测试验证等场景:
🔹 实现无人值守自动化刷写,大幅提升产线 EOL 效率;
🔹 实时输出诊断服务名称、执行步骤、运行状态、成功 / 失败结果;
🔹 支持调试人员快速定位失败节点,降低排查成本;
🔹 可集成到 MES / 上位机系统,形成标准化自动化刷写工位。
03.方案实现原理
自动化刷写的核心是通过脚本控制 TSMaster 内部系统变量,实现诊断流程启动、执行、状态读取与结果回收。
该方案支持两种控制方式:COM 接口调用、RPC 远程过程调用,并通过UDP 套接字实现状态实时上报。
3.1 技术架构
1.配置层:提供统一参数配置入口,管理工程路径、刷写文件、诊断 ID、等核心参数;
2.控制层:由 Python 脚本通过 COM/RPC 接口实现 TSMaster 工程远程控制、配置解析与防呆校验;
3.采集层:TSMaster 内置 C 小程序实时读取诊断流程系统变量,获取服务执行状态与结果;
4.通信层:采用 UDP 本地套接字实现实时性的数据传输;
5.展示层:通过命令行日志 + 图形进度条完成流程状态可视化展示。
3.2 COM 自动化实现原理
通过 win32com 直接创建并控制 TSMaster 应用实例,无需手动打开工程,脚本可完成:
· 诊断工程加载
· 硬件通道配置
· 仿真启动
· 诊断流程执行
· 系统变量读写
COM 方式实现脚本:
global app
app = win32com.client.Dispatch("TSMaster.TSApplication")
com = app.TSCOM()
formMan = app.TSFormManager()
formMan.show_main_form()
app.set_current_application("TSMaster")
formMan.load_project(project_path, True) # 指定对应工程
app.set_can_channel_count(1)
app.connect() # 启动 TSMaster
3.3 RPC 远程控制实现原理
通过 TSMaster 内置 RPC 服务,实现外部脚本对已打开工程的远程控制,适用于需要人工干预与脚本协同的场景。
RPC方式实现脚本:
initialize_lib_tsmaster(appname)
namelist = pchar()
get_active_application_list(namelist)
app_name_list = namelist.value.decode().split(';')
rpc_tsmaster_create_client(app_name_list[1].encode(), rpchandle)
rpc_tsmaster_activate_client(rpchandle, True)
rpc_tsmaster_cmd_start_simulation(rpchandle)
使用RPC方式需要额外在TSMaster中设置本地RPC,如下图所示:
Note:COM 与 RPC 仅连接方式不同,刷写逻辑、配置读取、UDP 通信、防呆校验等模块完全通用。
3.4 核心实现
3.4.1 Python 核心代码
防呆校验:
用于检查输入app/boot或者工程文件是否合规是否存在。
def check_config():
global setting_dict
driver=setting_dict['Driver1']
data=setting_dict['Data1']
profile=setting_dict['ProjectFullFile']
if driver == "":
return "Flash driver missing"
if not os.path.exists(driver):
return "Flash driver does not exist"
if data == "":
return "APP hex missing"
if not os.path.exists(data):
return "APP hex file does not exist"
if profile == "":
return "Project missing"
if not os.path.exists(profile):
return "Project file does not exist"
return "success"
配置文件读取:
def read_ini(setting_path):
setting = ConfigParser()
# 读取setting ini文件
setting.read(setting_path) # config.ini为你要读取的ini文件名
# setting获取配置值
setting_dict['ProjectFullFile'] = setting.get('Project', 'ProjectFullFile')
# print(f"ProjectFullFile value: {setting_dict['ProjectFullFile']}")
setting_dict['DownLoadAuto'] = setting.get('Project', 'DownLoadAuto')
setting_dict['Result'] = setting.get('Result', 'Result')
setting_dict['Enforcemode'] = setting.get('Project', 'Enforcemode')
setting_dict['PowerOn'] = setting.get('GeneralSettings', 'PowerOn')
setting_dict['Data1'] = setting.get('Data1', 'file_path')
setting_dict['Driver1'] = setting.get('Driver1', 'file_path')
setting_dict['FlowName'] = setting.get('DiagnosticFlow', 'FlowName')
setting_dict['DiagnosticName'] = setting.get('DiagnosticFlow', 'DiagnosticName')
setting_dict['SeedKeys'] = setting.get('SecurityAccess', 'SeedKeys')
setting_dict['requestId'] = setting.get('DiagnosticId', 'requestId')
setting_dict['responseId'] = setting.get('DiagnosticId', 'responseId')
setting_dict['functionId'] = setting.get('DiagnosticId', 'functionId')
进度条可视化:
class ProgressPopup:
def __init__(self):
self.root = None
self.progress = None
self.label = None
def show(self):
"在独立线程中显示弹窗"
def create_window():
self.root = tk.Tk()
self.root.title("UDS诊断进度")
self.root.geometry("300x120")
self.root.attributes('-topmost', True) # 置顶显示
self.label = tk.Label(self.root, text="诊断进度:", font=("Arial", 10))
self.label.pack(pady=5)
self.progress = ttk.Progressbar(self.root, length=250, mode='determinate')
self.progress.pack(pady=10)
self.percent = tk.Label(self.root, text="等待数据...", font=("Arial", 10))
self.percent.pack()
self.root.mainloop()
thread = threading.Thread(target=create_window, daemon=True)
thread.start()
def update(self, value):
if self.root and self.progress:
self.root.after(0, lambda: self._update_ui(value))
def _update_ui(self, value):
self.progress['value'] = value
self.percent.config(text=f"{value:.2f}%")
if value >= 100:
messagebox.showinfo("完成", "UDS刷写完成!")
self.root.destroy()
progress_popup = ProgressPopup()
progress_popup.show()
UDP 服务端(接收状态日志):
在24年版本(2024.5.24及之后)的诊断流程中新增加了Uds Flow 1_Step State系统变量,用于获取刷写状态字符串,可用于将刷写状态进行回传。
整体通信逻辑为TSMaster(客户端,端口 20001)监听 Python 脚本(服务端,端口 30001)的 UDP 报文,实现流程状态实时回传。
def sock_connect(UDP_IP,UDP_PORT):
global sock
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind((UDP_IP,UDP_PORT))
定义了一个名为 sock_connect 的函数,建立了一个基于UDP协议的套接字连接,并将其绑定到指定的IP地址和端口号上。
def rececv_data():
while isRecv:
bufsize = 1024
data , addr = sock.recvfrom(bufsize)
print(data.decode())
定义接收数据,在循环中接收UDP套接字(sock)接收到的数据,并将接收到的数据解码并打印出来。
def start_thread():
global t1
t1 = threading.Thread(target=rececv_data)
t1.start()
创建一个线程(t1)来执行另一个函数 receive_data,从而在一个独立的线程中接收UDP套接字的数据。
3.4.2 TSMaster C 小程序代码(UDP 发送状态)
C 小程序运行于 TSMaster 内部,负责系统变量读取与 UDP 报文发送,主要步骤为:
套接字初始化:创建 UDP 套接字,绑定本地 IP 与端口(20001),配置服务端地址(端口30001)。
clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
clientAddr.sin_family = AF_INET;
clientAddr.sin_port = htons(20001);
clientAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(clientSocket, (sockaddr*)&clientAddr, sizeof(clientAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(30001);
serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
变量监听:通过系统变量接口获取诊断流程步骤状态(Diagnostic0.Uds Flow 1_Step State)。
数据上报:将流程状态通过 UDP 发送至 Python 服务端,实现状态实时同步。
char s[512];
s32 ret = app.get_system_var_string("Diagnostic0.Uds Flow 1_Step State", 512, &s[0]);
if (ret == 0) {
sendto(clientSocket, s, strlen(s), 0, (sockaddr*)&serverAddr, sizeof(serverAddr));
log("%s", s);
}
Setting.ini配置文件:
配置文件用于定义自动化刷写核心参数,包含工程路径、烧录模式、硬件配置、文件路径、诊断参数、安全算法、通信 ID 等关键配置项,示例如下:
[Project] ——TSMaster工程文件夹
ProjectFullFile=C:\Users\dengzhiping\Desktop\demo\project ——工程路径
DownLoadAuto = 1 ——是否自动烧录,1自动烧录,0不自动烧录
Enforcemode = 0 ——是否强刷,1强刷,0不强刷
[Result]
Result = 3 ——刷写结果
[GeneralSettings]
PowerOn = 1 ——是否需要重新上下电
HardWare = 16
[Data1] ——BOOT或者APP文件路径
file_path = C:\Users\dengzhiping\Desktop\demo\auto_demo
[Driver1] ——FlashDriver文件路径
file_path = C:\Users\dengzhiping\Desktop\demo\auto_demo
[DiagnosticFlow]
FlowName = Uds Flow 1 ——诊断流程名
DiagnosticName = Diagnostic0 ——流程ID
[SecurityAccess]
SeedKeys=xxxxx ——安全算法(可选)
[DiagnosticId]
requestId = 0x7C0 ——请求(物理)ID
responseId = 0x7C8 ——应答ID
functionId = 0x7DF ——功能ID
04.运行效果展示
最终呈现的方式:python文件会被用户侧打包为一个exe文件,或者处理为bat文件,方便客户去调用自动化刷写。如果正常刷写完成,会自动退出当前工程;若刷写失败,则不退出当前工程,并且抛出failed。
(刷写文件路径不存在)
(项目工程路径不存在)
测试防呆校验
命令行中可以显示刷写流程
创建一个bat文件,双击运行,也可以在命令行窗口看到实时的刷新结果,若某一诊断服务失败,则显示Failed,并且不自动关闭工程。
刷写流程Failed
初始化等待刷新进度条
刷写中&刷写完成提示
05.常见问题与解答
Q1:程序发生异常,请检查ini文件中工程路径是否正确?
A:这个是配置的ini文件中工程路径不对,或者没有正确安装TSMaster,导致打开工程指定不到TSMaster。
Q2:系统报错OSError: [WinError 10048] 通常每个套接字地址(协议/网络地址/端口)只允许使用一次?
A:在网络编程中,一个套接字地址由协议(例如TCP或UDP)、网络地址(例如IP地址)和端口号组成。这个错误通常在尝试在相同的地址上创建多个套接字时发生,操作系统默认情况下不允许多个套接字绑定到相同的地址。一般发生在生成exe之后,打开会出现此错误,需要脚本里边重新更改端口号。
Q3:显示“打开ini文件错误或者是ini文件格式错误!KeyError: 'Driver1'”?
A:该报错是由于ini配置文件名不对,或者没有找到键值'Driver1',确认Setting配置文件是否存在,再者检查是否存在Driver1这个键值。
Q4:工程文件路径配置对了,为什么还是提醒工程Project file does not exist?
A:需要检查工程路径下有中文,有中文或者特殊字符都会出现识别不了情况。
Q5:本地存在多个刷写项目,如何打开指定的刷写工程?
A:COM口可以在setting配置文件中传入指定工程文件的路径,RPC方式可以指定获取到的app_name_list,若只有一个app_name_list[0],若有多个根据开启的RPC服务端名称确认(如TSMaster1对应app_name_list[1])。
Q6:两种调用方式存在什么区别?
A:COM接口可以实现在工程未打开情况下自动调用打开,RPC则需要要求工程处于开启状态,通过脚本或其他上位机直接控制,看实际适配场景进行选择。
Q7:工程路径正确但提示文件不存在?
A:工程路径包含中文或特殊字符,导致解析异常,将工程与文件放置于纯英文路径,避免特殊符号。
本方案基于TSMaster平台,充分利用其开放的COM/RPC自动化接口及系统变量监听能力,搭配Python脚本实现配置解析、防呆校验、UDP通信与可视化展示,最终形成一套高效率、可观测、可追溯、易调试的自动化刷写方案。无论是产线EOL批量刷写,还是实验室调试验证,都能显著提升效率、降低排查成本。欢迎尝试并集成到您的TSMaster工作流中。