尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Python批量解析CANoe BLF日志:自动化提取UDS诊断否定响应码(NRC)

Python批量解析CANoe BLF日志:自动化提取UDS诊断否定响应码(NRC) 在汽车电子诊断测试中我们经常需要分析海量的CANoe录制的.blf日志文件从中筛选出包含特定诊断否定响应码NRC的报文。手动在CANoe的Trace窗口里一页页翻找不仅效率低下还容易遗漏。本文将分享一套基于Python的自动化解决方案教你如何批量扫描.blf文件精准定位包含指定NRC的UDS诊断报文并提取关键上下文信息极大提升测试数据分析效率。无论你是负责诊断协议测试的工程师还是希望深入理解CANoe数据后处理的开发者这套脚本都能成为你的得力工具。我们将从.blf文件格式和NRC概念讲起逐步搭建完整的Python解析环境最终实现一个功能完善的批量扫描工具并附上详细的代码注释和避坑指南。1. 背景与核心概念为什么需要批量扫描NRC在深入代码之前我们有必要厘清几个核心概念这有助于理解整个工具的设计目标。1.1 什么是CANoe与.blf文件CANoe是Vector公司推出的一款广泛应用于汽车总线网络开发、测试和分析的软件工具。它支持CAN、LIN、FlexRay、Ethernet等多种总线系统。在测试过程中CANoe可以将总线上流通的所有报文包括应用数据、网络管理、诊断报文等录制下来保存为二进制日志文件最常见的格式就是.blf(Binary Logging Format)。一个.blf文件可能包含数小时甚至数天的总线数据数据量非常庞大。1.2 什么是UDS与NRCUDSUnified Diagnostic Services统一诊断服务是汽车电子领域用于对ECU电子控制单元进行诊断和编程的标准协议ISO 14229。我们常说的诊断仪就是通过UDS协议与ECU通信。在UDS通信中ECU对诊断请求的响应分为两种肯定响应Positive Response格式为0x40 服务ID表示请求被成功执行。否定响应Negative Response格式固定为0x7F后跟请求的服务ID和否定响应码NRC。NRCNegative Response Code是一个单字节的值它精确地指出了请求失败的原因。例如0x11ServiceNotSupported不支持该服务0x12SubFunctionNotSupported不支持该子功能0x13IncorrectMessageLengthOrInvalidFormat消息长度错误或格式无效0x22ConditionsNotCorrect条件不满足0x31RequestOutOfRange请求超出范围0x33SecurityAccessDenied安全访问被拒绝0x35InvalidKey无效密钥0x72GeneralProgrammingFailure常规编程失败在诊断测试中我们经常需要验证ECU在特定异常条件下如非法密钥、条件不满足是否正确返回了预期的NRC。因此从庞大的.blf日志中快速找出所有包含特定NRC如0x35的报文记录是分析测试结果、编写测试报告的关键步骤。1.3 手动分析的痛点与自动化需求手动在CANoe中分析.blf文件通常是这样操作的打开文件在Trace窗口过滤出诊断报文然后肉眼逐条检查响应报文记录NRC。这个过程存在几个明显问题效率极低面对GB级别的日志文件手动翻找如同大海捞针。容易出错人眼疲劳可能导致遗漏。难以追溯上下文找到NRC后还需要手动查看其对应的请求报文、时间戳等上下文信息过程繁琐。无法批量处理当需要分析成百上千个测试用例生成的日志时手动方式完全不可行。因此开发一个能够自动、批量、精准解析.blf文件并提取NRC相关信息的脚本工具具有强烈的工程实践价值。2. 环境准备与工具选型我们的目标是使用Python编写一个跨平台的脚本。以下是核心工具栈操作系统Windows 10/11, macOS, Linux (理论上均支持但CANoe相关库在Windows上最稳定)Python版本 3.7核心库canlib/vector-asc/blf这是解析.blf文件的关键。有多种库可以选择本文将使用一个相对直接且功能足够的库python-blf。辅助库pandas(用于数据整理和输出),tqdm(用于显示进度条)开发环境任何你喜欢的IDE或编辑器如PyCharm, VSCode等。2.1 创建项目与安装依赖首先创建一个新的项目目录并初始化虚拟环境推荐。# 创建项目目录 mkdir blf_nrc_scanner cd blf_nrc_scanner # 创建虚拟环境 (Windows) python -m venv venv venv\Scripts\activate # 创建虚拟环境 (macOS/Linux) python3 -m venv venv source venv/bin/activate接下来安装必需的Python库。我们将主要使用blf和pandas。pip install blf pandas tqdm注意python-blf库可能不是最官方的Vector解析库但它提供了基础的BLF读取功能且安装简单。对于更复杂的需求如解析CAN FD、LIN、Ethernet可能需要考虑Vector提供的CANoe COM接口或vxlapi但那些通常需要安装CANoe运行环境且编程接口更复杂。本文以轻量级、独立运行为目标。2.2 项目结构设计我们的项目结构将保持清晰blf_nrc_scanner/ ├── venv/ # Python虚拟环境忽略 ├── data/ # 存放待分析的.blf文件 │ ├── test_log1.blf │ └── test_log2.blf ├── output/ # 存放扫描结果 ├── nrc_scanner.py # 主脚本文件 ├── requirements.txt # 依赖列表 └── README.md # 项目说明你可以将需要分析的.blf文件放入data文件夹。output文件夹用于存放脚本生成的报告。3. 核心原理与脚本设计拆解在动手编码前我们先梳理一下脚本需要完成的任务和背后的逻辑。3.1 .blf文件解析基础.blf文件内部由一系列“块Blocks”组成每个块代表一条记录例如一条CAN报文、一个时间戳事件或一个文件注释。我们需要的是CAN报文块。每条CAN报文记录通常包含以下关键信息时间戳Timestamp报文发生的精确时间。通道Channel报文来自哪个CAN通道。标识符CAN ID / Arbitration ID报文的ID用于区分报文类型。诊断请求/响应通常使用固定的功能寻址或物理寻址ID如0x7DF(功能寻址请求),0x7E0(ECU响应) 等具体取决于网络设计。数据长度DLC报文数据域的长度。数据Data报文实际承载的数据以字节数组形式存储。3.2 识别UDS诊断报文与NRC并非所有CAN报文都是UDS诊断报文。我们需要通过以下逻辑进行过滤和识别过滤CAN ID首先只关注用于诊断的CAN ID。例如假设诊断请求ID为0x7DF响应ID为0x7E8。你需要根据你的实际项目DBC或通信矩阵来设置这些ID。识别UDS帧UDS报文有特定的格式。通常单帧UDS报文数据域的第一个字节是PCIProtocol Control Information对于单帧其高4位为0低4位表示数据长度。紧随其后的字节是服务IDSID。请求报文SID 具体的诊断服务如0x10(会话控制),0x27(安全访问)。肯定响应SID 0x40 请求SID。否定响应SID 0x7F后面紧跟请求的SID和NRC。提取NRC对于一条CAN报文如果其CAN ID是诊断响应ID且数据域长度足够并且第一个数据字节或根据PCI调整后的位置是0x7F那么这条报文就是一个否定响应。NRC通常位于0x7F和请求SID之后的那个字节。示例一条否定响应报文数据为[0x7F, 0x27, 0x35]。0x7F表示否定响应。0x27表示这是对0x27(安全访问) 服务的响应。0x35这就是NRC表示InvalidKey。3.3 脚本工作流程设计我们的主脚本nrc_scanner.py将遵循以下流程遍历输入目录扫描指定文件夹如./data下的所有.blf文件。解析单个.blf文件使用blf库打开文件迭代读取每一条CAN报文记录。应用过滤规则 a. 检查CAN ID是否为诊断响应ID。 b. 检查数据域是否以0x7F开头或根据PCI判断。 c. 提取NRC字节。 d. 判断提取的NRC是否与用户指定的目标NRC列表匹配。记录匹配的报文如果匹配则收集该条报文的详细信息时间戳、通道、CAN ID、原始数据、NRC值以及其上下文如前一条请求报文。输出结果将当前文件的所有匹配结果整理成一个列表最后汇总所有文件的结果生成结构化的报告如CSV文件便于后续分析。4. 完整实战编写批量扫描脚本下面我们一步步实现nrc_scanner.py。4.1 导入必要的库# nrc_scanner.py import os import sys import argparse from pathlib import Path from typing import List, Dict, Any, Optional, Tuple import blf import pandas as pd from tqdm import tqdm4.2 定义核心配置与常量我们需要定义一些常量这些值需要你根据实际项目修改。# 用户配置区域 (请根据实际项目修改) # 诊断报文的CAN ID (16进制表示) DIAG_REQUEST_ID 0x7DF # 诊断仪发送请求的CAN ID DIAG_RESPONSE_ID 0x7E8 # ECU回复响应的CAN ID # 你想要搜索的NRC列表 (16进制) TARGET_NRC_LIST [0x35, 0x22, 0x31] # 例如搜索InvalidKey, ConditionsNotCorrect, RequestOutOfRange # 是否启用上下文关联寻找匹配的请求报文 ENABLE_CONTEXT_MATCHING True # 上下文搜索的时间窗口秒用于关联请求和响应 CONTEXT_TIME_WINDOW 0.5 # 500毫秒 # 配置结束 4.3 编写BLF文件解析与NRC识别函数这是最核心的函数负责读取BLF文件并找出目标NRC。def parse_blf_for_nrc(blf_file_path: str, target_nrc_list: List[int]) - List[Dict[str, Any]]: 解析单个.blf文件查找包含指定NRC的UDS否定响应报文。 Args: blf_file_path: .blf文件的完整路径。 target_nrc_list: 需要查找的NRC列表如 [0x35, 0x22]。 Returns: 一个字典列表每个字典代表一条匹配的NRC报文及其上下文信息。 如果文件无法解析或没有匹配项返回空列表。 matched_messages [] try: # 使用blf库打开文件 with blf.BLFReader(blf_file_path) as reader: # 为了关联上下文我们需要临时存储最近的诊断请求报文 recent_requests [] # 格式: (timestamp, channel, can_id, data) # 使用tqdm包装迭代器显示进度条 for msg in tqdm(reader, descfParsing {Path(blf_file_path).name}, unit msg): # msg 是一个 namedtuple字段包括: timestamp, channel, flags, id, dlc, data # 注意不同版本的blf库字段名可能略有不同常见的是 id 和 data can_id msg.id timestamp msg.timestamp channel msg.channel data msg.data # 这是一个bytes对象 # 1. 检查是否是诊断请求报文用于上下文关联 if ENABLE_CONTEXT_MATCHING and can_id DIAG_REQUEST_ID: # 清理过期的请求记录超出时间窗口 recent_requests [(ts, ch, cid, d) for (ts, ch, cid, d) in recent_requests if timestamp - ts CONTEXT_TIME_WINDOW] # 存储当前请求 recent_requests.append((timestamp, channel, can_id, data)) # 2. 检查是否是诊断响应报文 if can_id DIAG_RESPONSE_ID: # 检查数据长度是否足够包含UDS否定响应 if len(data) 3: # 最小否定响应: 0x7F SID NRC # 判断是否为否定响应 (0x7F) # 注意需要考虑PCI单帧第一字节。这里简化处理假设数据域直接以0x7F开头。 # 更严谨的做法是解析PCI判断是否为单帧且SF_DL3。 if data[0] 0x7F: # 提取NRC它位于第三个字节 (索引2) nrc_byte data[2] nrc_value nrc_byte # 直接是整数 # 3. 检查NRC是否在目标列表中 if nrc_value in target_nrc_list: match_info { file_name: Path(blf_file_path).name, timestamp: timestamp, channel: channel, can_id_hex: f0x{can_id:03X}, data_hex: data.hex().upper(), nrc_hex: f0x{nrc_value:02X}, nrc_decimal: nrc_value, matched_request: None } # 4. 尝试关联上下文匹配的请求报文 if ENABLE_CONTEXT_MATCHING and recent_requests: # 寻找时间最近、通道相同的请求报文 for req_ts, req_ch, req_id, req_data in reversed(recent_requests): if req_ch channel and abs(timestamp - req_ts) CONTEXT_TIME_WINDOW: match_info[matched_request] { timestamp: req_ts, can_id_hex: f0x{req_id:03X}, data_hex: req_data.hex().upper() } # 找到第一个匹配的请求后就跳出 break matched_messages.append(match_info) except Exception as e: print(f错误解析文件 {blf_file_path} 时发生异常: {e}, filesys.stderr) return matched_messages关键点解释blf.BLFReader是一个迭代器逐条读取BLF中的记录。我们维护一个recent_requests列表来缓存最近的诊断请求用于后续响应报文的上下文关联。判断否定响应的逻辑data[0] 0x7F是一个简化版。在真实的多帧传输如ISO-TP中需要先解析PCI。如果你的诊断报文使用了ISO-TP传输协议数据域的第一个字节是PCI0x7F可能出现在后续位置。你需要根据实际协议调整解析逻辑。我们假设NRC在数据域的第三个字节索引2这符合单帧UDS否定响应的标准格式0x7F SID NRC。4.4 编写批量处理与主函数现在我们编写遍历目录和处理所有文件的函数以及主程序入口。def scan_directory_for_nrc(input_dir: str, output_file: str, target_nrc_list: List[int]) - None: 扫描指定目录下所有的.blf文件生成NRC扫描报告。 Args: input_dir: 包含.blf文件的输入目录路径。 output_file: 输出CSV报告的文件路径。 target_nrc_list: 需要查找的NRC列表。 input_path Path(input_dir) if not input_path.exists() or not input_path.is_dir(): print(f错误输入目录 {input_dir} 不存在或不是一个目录。) return # 查找所有.blf文件 blf_files list(input_path.glob(*.blf)) if not blf_files: print(f提示在目录 {input_dir} 中未找到任何.blf文件。) return print(f找到 {len(blf_files)} 个.blf文件开始扫描...) all_matches [] for blf_file in blf_files: print(f\n处理文件: {blf_file.name}) matches parse_blf_for_nrc(str(blf_file), target_nrc_list) if matches: print(f 找到 {len(matches)} 条匹配的NRC记录。) all_matches.extend(matches) else: print(f 未找到匹配的NRC记录。) # 将结果转换为DataFrame并保存 if all_matches: df pd.DataFrame(all_matches) # 调整列顺序使其更易读 column_order [file_name, timestamp, channel, can_id_hex, nrc_hex, nrc_decimal, data_hex, matched_request] # 确保列存在 df df.reindex(columns[col for col in column_order if col in df.columns]) df.to_csv(output_file, indexFalse, encodingutf-8-sig) print(f\n扫描完成共找到 {len(all_matches)} 条匹配记录。) print(f详细报告已保存至: {output_file}) # 在控制台简单预览前几条记录 print(\n报告预览前5行:) print(df.head().to_string()) else: print(\n扫描完成在所有文件中均未找到指定的NRC。) def main(): 主函数解析命令行参数并启动扫描。 parser argparse.ArgumentParser(description批量扫描BLF文件中包含指定NRC的UDS诊断报文。) parser.add_argument(-i, --input, typestr, default./data, help包含.blf文件的输入目录路径 (默认: ./data)) parser.add_argument(-o, --output, typestr, default./output/nrc_scan_report.csv, help输出CSV报告的文件路径 (默认: ./output/nrc_scan_report.csv)) parser.add_argument(-n, --nrc, typestr, requiredFalse, help要搜索的NRC列表以逗号分隔的16进制数 (例如: 35,22,31)。若未指定则使用脚本内定义的TARGET_NRC_LIST。) args parser.parse_args() # 处理NRC参数 if args.nrc: try: target_nrc_list [int(nrc_str.strip(), 16) for nrc_str in args.nrc.split(,)] except ValueError: print(错误NRC参数格式无效。请使用16进制数用逗号分隔如 35,22,31。) sys.exit(1) else: target_nrc_list TARGET_NRC_LIST print(f提示使用脚本内定义的NRC列表: {[hex(n) for n in TARGET_NRC_LIST]}) # 确保输出目录存在 output_path Path(args.output) output_path.parent.mkdir(parentsTrue, exist_okTrue) # 开始扫描 scan_directory_for_nrc(args.input, args.output, target_nrc_list) if __name__ __main__: main()4.5 运行与验证脚本现在我们可以测试脚本了。准备测试数据将你的.blf文件放入./data目录。如果没有现成的可以暂时不放脚本会提示未找到文件。运行脚本# 使用默认配置扫描./data输出到./output使用脚本内定义的NRC列表 python nrc_scanner.py # 指定输入目录和NRC列表 python nrc_scanner.py -i ./my_logs -o ./my_report.csv -n 35,22 # 在Windows上如果遇到编码问题可以指定UTF-8输出 # 脚本已使用 utf-8-sig 编码保存CSV通常无需额外操作。查看输出脚本运行后会在控制台显示进度和简要结果。完整的报告将保存为CSV文件如nrc_scan_report.csv。你可以用Excel或文本编辑器打开它。CSV报告示例file_nametimestampchannelcan_id_hexnrc_hexnrc_decimaldata_hexmatched_requesttest_log1.blf12345.67890110x7E80x35537F2735{timestamp: 12345.678500, can_id_hex: 0x7DF, data_hex: 2711}test_log1.blf12346.12345610x7E80x22347F1022{timestamp: 12346.123000, can_id_hex: 0x7DF, data_hex: 1001}5. 常见问题与排查思路在实际使用中你可能会遇到一些问题。以下是常见问题的排查指南。问题现象可能原因解决思路脚本运行报错ModuleNotFoundError: No module named blfpython-blf库未正确安装。确认虚拟环境已激活并重新执行pip install blf。检查PyPI上库的名称有时可能是blf-reader。成功运行但找不到任何NRC记录1. BLF文件中确实没有目标NRC。2.诊断ID配置错误脚本中的DIAG_REQUEST_ID和DIAG_RESPONSE_ID与实际日志不匹配。3.NRC列表错误目标NRC不在列表中。4.报文格式不匹配UDS报文可能使用了ISO-TP多帧传输0x7F不在数据域第一个字节。1. 用CANoe打开BLF文件手动确认是否存在目标NRC。2. 在CANoe Trace中查看诊断报文的CAN ID并更新脚本常量。3. 核对NRC值。4. 需要增强解析逻辑先识别ISO-TP单帧/多帧再定位NRC。找到的NRC记录数量远少于预期上下文关联时间窗口CONTEXT_TIME_WINDOW设置过小导致请求报文在响应到来前已被清理。适当增大CONTEXT_TIME_WINDOW的值例如从0.5改为1.0或2.0秒。观察CANoe中请求与响应的时间间隔。matched_request字段为空1. 未启用上下文关联 (ENABLE_CONTEXT_MATCHINGFalse)。2. 请求报文在时间窗口内未被捕获可能被过滤掉了。3. 请求和响应不在同一CAN通道。1. 确保ENABLE_CONTEXT_MATCHING为True。2. 增大时间窗口。3. 检查脚本中通道匹配的逻辑确保请求和响应的channel字段一致。脚本解析速度很慢BLF文件非常大几百MB以上逐条解析需要时间。这是正常现象。可以尝试1. 使用更高效的库如Vector官方库。2. 如果只关心特定通道或时间段的报文可以在解析循环早期添加过滤条件减少处理量。报错‘BLFReader’ object has no attribute ‘__enter__’使用的blf库版本或API与示例代码不兼容。检查blf库的官方文档或源码看如何正确打开和读取文件。可能需要使用blf.Reader()而不是blf.BLFReader()。6. 进阶优化与最佳实践基础的脚本已经可以工作但在生产环境中我们还需要考虑更多。6.1 增强解析鲁棒性支持ISO-TP上述简化版解析器假设UDS报文是单帧。现实中诊断报文经常通过ISO-TPISO 15765-2传输数据域第一个字节是PCI。我们需要升级parse_blf_for_nrc函数中的解析逻辑。def is_uds_negative_response(data: bytes) - Tuple[bool, Optional[int]]: 判断一个字节序列是否为UDS否定响应并提取NRC。 支持单帧ISO-TP。 Args: data: 报文数据域的字节序列。 Returns: (is_negative, nrc_value): 如果是否定响应且能提取NRC返回(True, nrc)否则返回(False, None)。 if len(data) 1: return False, None # 解析PCI (Protocol Control Information) pci_byte data[0] pci_type (pci_byte 0xF0) 4 # 取高4位 if pci_type 0: # 单帧 (Single Frame) sf_dl pci_byte 0x0F # 取低4位表示数据长度 # 检查数据长度是否足够容纳UDS否定响应 (PCI 0x7F SID NRC) if sf_dl 3 and len(data) 4: # data[0]是PCI所以总长度至少为4 uds_payload_start 1 # UDS数据从索引1开始 if data[uds_payload_start] 0x7F: # 否定响应标识 # NRC在 UDS payload 的第三个字节 (PCI之后: 0x7F, SID, NRC) nrc_value data[uds_payload_start 2] return True, nrc_value # 可以在此扩展处理首帧、连续帧、流控帧等 return False, None # 然后在 parse_blf_for_nrc 函数中替换原来的判断逻辑 # 原来的 # if data[0] 0x7F: # nrc_byte data[2] # ... # 改为 is_negative, nrc_value is_uds_negative_response(data) if is_negative and nrc_value is not None: # 检查 nrc_value 是否在 target_nrc_list 中...6.2 处理多种诊断ID和通道项目中可能存在多个ECU使用不同的诊断ID。我们可以将诊断ID配置为一个列表。# 配置区域修改 DIAG_RESPONSE_IDS [0x7E8, 0x7E9, 0x7EA] # 多个ECU的响应ID DIAG_REQUEST_IDS [0x7DF, 0x7E0, 0x7E1] # 对应的请求ID用于上下文关联 # 在解析循环中修改判断条件 if ENABLE_CONTEXT_MATCHING and can_id in DIAG_REQUEST_IDS: # ... 存储请求 if can_id in DIAG_RESPONSE_IDS: # ... 检查是否为否定响应6.3 输出更丰富的报告除了CSV我们可以生成更易读的HTML报告或按NRC、按文件进行统计汇总。def generate_summary_report(df: pd.DataFrame, output_summary_path: str): 生成统计摘要报告。 if df.empty: print(没有数据可生成摘要。) return summary { total_matches: len(df), files_affected: df[file_name].nunique(), nrc_distribution: df[nrc_hex].value_counts().to_dict(), channel_distribution: df[channel].value_counts().to_dict(), } # 按文件统计 file_stats df.groupby(file_name).agg({ nrc_hex: count, channel: lambda x: x.mode().iloc[0] if not x.mode().empty else None }).rename(columns{nrc_hex: nrc_count}).to_dict(index) import json with open(output_summary_path, w, encodingutf-8) as f: json.dump({summary: summary, details_by_file: file_stats}, f, indent2, ensure_asciiFalse) print(f统计摘要已保存至: {output_summary_path})6.4 集成到CI/CD或测试流水线你可以将此脚本封装成命令行工具在自动化测试结束后自动运行。例如在Jenkins或GitLab CI的Pipeline中增加一个步骤# .gitlab-ci.yml 示例片段 analyze_blf_logs: stage: post-test script: - python -m pip install -r requirements.txt - python nrc_scanner.py -i ${CI_PROJECT_DIR}/test_logs -o ${CI_PROJECT_DIR}/reports/nrc_report.csv -n 35,22,31 artifacts: paths: - reports/nrc_report.csv expire_in: 1 week6.5 性能优化建议并行处理如果有多核CPU可以使用concurrent.futures库并行解析多个BLF文件。增量扫描记录已扫描文件的MD5和最后修改时间下次只扫描新增或修改的文件。使用更底层的库对于超大型BLF文件python-blf可能不是最快的。可以研究使用Vector提供的CANoe Automation或vxlapi的Python接口它们通常性能更高但依赖CANoe环境。7. 总结本文详细介绍了如何利用Python批量扫描CANoe的BLF日志文件自动提取包含特定NRC的UDS诊断报文。我们从需求痛点出发逐步构建了一个完整的解决方案理解基础明确了.blf文件、UDS协议和NRC的概念。搭建环境选择了python-blf和pandas等库搭建了独立的解析环境。设计流程规划了文件遍历、报文解析、NRC识别、上下文关联和结果输出的完整流程。编码实现提供了可直接运行的核心脚本并附有详细注释。排查问题列出了使用过程中可能遇到的常见问题及解决方法。进阶优化提出了支持ISO-TP、多ID处理、丰富报告和性能优化的方向。这个工具的价值在于将测试工程师从繁琐重复的手工劳动中解放出来实现诊断测试结果的自动化、标准化分析。你可以在此基础上根据自己项目的具体协议如J1939、DoIP、报文格式和报告需求进行定制和扩展。下一步学习建议深入研究ISO 15765-2 (ISO-TP) 协议完善多帧报文的解析。探索CANoe的COM自动化接口实现更强大的交互式分析如自动重播特定报文序列。将NRC扫描与测试用例管理系统关联实现自动化的测试结果判定。学习使用struct模块更高效地解析二进制数据。希望这份教程能为你高效处理汽车诊断测试数据打开一扇门。如果在使用中遇到新的问题欢迎在评论区交流探讨。
返回列表