news 2026/10/14 2:06:37

SavvyCAN Range State 窗口实战:利用平滑度启发式搜索候选 CAN 信号

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SavvyCAN Range State 窗口实战:利用平滑度启发式搜索候选 CAN 信号
  • 开发工具
  • 逆向工程
  • 嵌入式

【免费下载链接】SavvyCAN

QT based cross platform canbus tool

项目地址:https://gitcode.com/gh_mirrors/sa/SavvyCAN
点击查看免费下载

Range State(范围状态)窗口是 SavvyCAN(QT 跨平台 CAN 总线分析工具,仓库根目录见 README.md)中一个独特的“信号猎手”工具:它不依赖 DBC 文件,而是通过统计启发式在原始 CAN 帧数据里自动筛选出“看起来像有意义物理量”的信号候选。本文以官方帮助文档 help/rangestate.md 为主体,结合源码 re/rangestatewindow.cpp 深入讲解其工作机理,读完你将掌握参数调优方法、候选信号筛选技巧,以及如何快速从海量 CAN 数据中定位车速、转速等平滑变化信号。

窗口定位:从“有规律的跳动”里找信号

窗口的目的是搜索“看起来可能很重要”的信号。正如官方帮助文档所描述的,这是一个比较模糊的定义——核心思想是找出**变化相对连贯(coherently)**的信号。观察图中的示例信号曲线:它有一些跳变,但整体看起来“像是有含义的东西”,这就是这个窗口的筛选逻辑。

需要特别说明的是:该工具必然会产生大量误报(false positives),但即便如此,它依然能提供不错的候选方向。最终判定某个信号是否重要、是否可用的工作,仍然需要你自己完成。它的典型使用场景是:当你没有任何 DBC 文件、需要逆向分析未知 CAN 报文时,用它快速圈定值得深入研究的位段。

在 SavvyCAN 中,该窗口由主窗口菜单的 “Range State” 动作触发(见 ui/mainwindow.ui 中的actionRange_State_2),经由MainWindow::showRangeWindow()创建并显示(mainwindow.cpp),窗口类RangeStateWindow定义于 re/rangestatewindow.h 与 re/rangestatewindow.cpp。

使用前必须设置的 7 项参数

使用该窗口前,需要按顺序配置以下参数(控件定义见界面文件 ui/rangestatewindow.ui):

  1. ID Filter 列表——取消勾选任何你不想搜索的 CAN ID。列表由窗口打开时自动从当前已采集帧中提取(refreshFilterList()遍历模型中的所有CANFrame,为每个出现过的 ID 创建一个带复选框的过滤项,见 re/rangestatewindow.cpp)。列表下方的 “All / None” 按钮可一键全选或全不选,实际生效状态记录在idFilters这个QMap<int, bool>中。

  2. Sensitivity(灵敏度)——这是一个主观性度量。它对结果的影响不算大,但在两个极端之间来回调整,会改变程序对“什么算是相关信号”的判断。底层实现中滑杆范围为 10~250(见 ui/rangestatewindow.ui 中slideSensitivity的 minimum/maximum),并通过线性插值换算成一个 0.0~1.0 的采样点参与后续判定,具体见下文“候选判定算法”。

  3. Min Signal Size(最小信号尺寸)——你想搜索的最小信号位宽,最小可到 1 bit(如果你足够“大胆”的话)。界面允许范围 1~32。

  4. Max Signal Size(最大信号尺寸)——最大位宽。Min 与 Max 之间的跨度直接决定整个搜索过程耗时。例如设置 Min=8、Max=16,程序会依次搜索 8、9、10、…、16 bit 的信号;由于同一组基础位会被反复覆盖,结果里会出现重复候选。

  5. Granularity(粒度)——设置“位跳宽度”(bit jump width),即每次搜索新信号时向后移动的 bit 数。粒度为 1、最小位宽 8 时,程序会从 bit 0 开始搜索 8 bit 信号,再从 bit 1、bit 2……依次推进;粒度为 8 时则从 bit 0、bit 8、bit 16……开始。很多信号恰好落在字节边界上,因此粒度为 8 意味着所有搜索都从字节边界起步,对大多数情况足够;但有些设计者会把信号放在不对齐的边界上,此时需要更细的粒度才能找到它们。

  6. Signal Mode(信号模式)——针对超过 8 bit 的信号的字节序选择。信号可以是大端(big endian)或小端(little endian),即信号的 bit 0 对应最高还是最低数值位。你可以只搜大端、只搜小端,或者“Try Both”两种都试。CAN 设备开发者通常会统一采用某一种字节序,但并非总是如此。下拉框三个选项在构造函数中依次加入(re/rangestatewindow.cpp)。

  7. Signed Mode(有符号模式)——同理,任何超过 1 bit 的信号都可能是有符号(最高位为 1 表示负数、0 表示正数)或无符号。你可以只搜无符号、只搜有符号,或两种都试。信号什么时候会被设计成有符号其实没有固定规律,两种都可能,所以除非你非常确定,最稳妥的做法是允许程序两种都试,再由你从结果中挑选看起来最合理的。

补充说明:由于信号可能跨字节边界,即使位宽不超过 8 bit,也必须同时尝试两种字节序(源码 re/rangestatewindow.cpp 的注释明确说明了这一点)。

执行计算:点击 “Recalculate Candidate Signals”

参数配置完成后,点击 “Recalculate Candidate Signals” 按钮(btnRecalc)触发recalcButton()(re/rangestatewindow.cpp)。该过程会:

  1. 清空候选列表、已找到信号集合与图表;
  2. 弹出无取消按钮的模态进度对话框(QProgressDialog);
  3. 按 ID 逐个处理:对每个被勾选的 ID,先把模型帧中所有同 ID 帧拷贝到frameCache(一次性预留足够空间),再调用signalsFactory()进行候选生成(re/rangestatewindow.cpp)。

计算量取决于你选择的参数组合:signalsFactory()中,信号尺寸从 Max 递减到 Min(步进为 Granularity),起始位从 bit 0 推进到frameCache首帧 payload 的 bit 总数,每个 (尺寸, 起始位) 组合还要根据 Signal Mode 和 Signed Mode 各尝试 1~4 种字节序/符号组合。因此文档建议“做好准备等待”——参数越宽、粒度越细,耗时越长。

候选判定算法:一阶/二阶差分如何识别“平滑信号”

这是整个窗口的核心原理。processSignal()(re/rangestatewindow.cpp)对每个候选信号执行如下判定链:

第一步:提取数值并计算范围。对frameCache中每一帧调用Utility::processIntegerSignal()(定义于 utility.h)取出该信号位的整数值,同时记录最低值与最高值。若最低值等于最高值,说明该信号从未变化,直接判定为无价值并返回(if (lowestValue == highestValue) return false;)。

第二步:范围门槛(range gate)。计算range = highestValue - lowestValue,并将其与信号类型允许的最大范围(有符号为1 << (bitLength - 1),无符号为1 << bitLength)比较。requiredRange通过Utility::Lerp()在“最大范围的 1%(低灵敏度)”与“最大范围的 20%(高灵敏度)”之间线性插值得到。范围不足的信号会被淘汰。

第三步:一阶差分(first order diff)检查。将数值减去最低值得到缩放序列,再对相邻值求差得到diff1。判定阈值comparisonValue = Lerp(range * 0.55, 0, lerpPoint),允许的超限次数maxOvers = Lerp(numFrames / 30.0, 2, lerpPoint)。若一阶差分绝对值超过阈值的次数太多,说明信号跳变剧烈,不是平滑的范围信号,直接淘汰。

第四步:二阶差分(second order diff)检查。对diff1再求差得到diff2,这相当于信号的“加速度”。平滑变化信号不应出现剧烈的加速度,因此阈值收紧为Lerp(range * 0.20, 1, lerpPoint),超限次数上限仅为Lerp(8, 2, lerpPoint)。这一关通过后,信号才被认定为候选。

其中灵敏度滑杆的换算公式为:lerpPoint = ((double)sensitivity - 10.0) / 240.0(re/rangestatewindow.cpp),而Utility::Lerp()是标准的线性插值value1 * (1 - samplePoint) + value2 * samplePoint(utility.h)。

解读候选列表:从编码看字段含义

通过判定的信号会出现在上方 “Candidate Signals” 列表中,每条记录包含:ID、起始位(startBit,注意位从 0 开始、最多到 63)、长度(len)、有符号/无符号、大端/小端。列表项的文本格式见 re/rangestatewindow.cpp。

候选信号在内部被编码为一个 64 位整数foundSignals条目(位段打包逻辑见 re/rangestatewindow.cpp),选中列表项时再按位解包还原(re/rangestatewindow.cpp):

位段含义
bit 0~31CAN 帧 ID
bit 32~39起始位 startBit
bit 40~47信号长度 bitLength
bit 48是否为有符号(Signed)
bit 49是否为大端(BigEndian)

快速浏览候选:键盘上下键 + 实时图表

在候选列表中点击或选中某个信号,其图形化曲线会立即出现在下方绘图区(clickedSignalList()重新按 ID 提取帧数据、解包位段并调用createGraph()绘制,见 re/rangestatewindow.cpp)。

特别实用的技巧是:使用键盘上、下方向键在列表间移动,甚至可以按住方向键让列表快速滚动,一边滚动一边观察图表,看到“合眼缘”的信号再停下来。因为候选信号动辄上百条,逐个点开查看非常繁琐,这种“滚动 + 目视”的浏览方式效率极高。

绘图区本身基于 QCustomPlot(界面文件 ui/rangestatewindow.ui 中引用qcustomplot.h),createGraph()会按数值范围自动缩放 Y 轴并在上下留出约 20% 的边距(re/rangestatewindow.cpp)。

实战:用图形直觉锁定车速类信号

这个窗口的实战价值在于:当你大致知道目标信号“应该长什么样”时,能快速把它从几百个候选中找出来。文档以车辆速度为例:

  • 车速不可能瞬间从 0 跳到 100,因此车速信号在时间轴上表现为大量连续上扬/下落的扫动曲线;
  • 通过快速浏览各候选的图形,很容易排除杂乱无章的位段,锁定那些“看起来像是速度”的候选;
  • 它可能是以 km/h 为单位的速度、可能是 mph、也可能是车轮 RPM——先找到形态符合的信号,再通过数值范围与车辆行为比对来确认具体含义。

与 SavvyCAN 数据流的联动机制

该窗口通过连接MainWindow::framesUpdated信号(re/rangestatewindow.cpp)感知帧数据变化:updatedFrames()处理三种情况——所有帧被删除(清空 ID 过滤列表)、加载全新帧集(重建过滤列表)、新增帧(自动为没出现过的 ID 补建过滤项并默认勾选,re/rangestatewindow.cpp)。注意:新增帧不会自动触发重新计算,必须手动点击 “Recalculate Candidate Signals” 才会生成新结果。

窗口还会在显示/关闭时通过readSettings()/writeSettings()读写位置与尺寸(受Main/SaveRestorePositions设置控制,re/rangestatewindow.cpp),并在按下 F1 时直接弹出本文所依据的帮助文档rangestate.md(re/rangestatewindow.cpp)。

小结

Range State 窗口把“信号是否平滑变化”这一逆向工程直觉,转化为可配置的统计判定流水线:位宽与粒度控制搜索覆盖范围,字节序与符号模式控制信号空间,灵敏度通过线性插值调节一阶/二阶差分的判定松紧。掌握这 7 项参数的取舍逻辑后,你就能在没有 DBC 文件的情况下,把成百上千条原始报文压缩成几十条值得细看的候选信号,是 CAN 逆向分析与未知协议探索中非常趁手的前期侦察工具。

  • 开发工具
  • 逆向工程
  • 嵌入式

【免费下载链接】SavvyCAN

QT based cross platform canbus tool

项目地址:https://gitcode.com/gh_mirrors/sa/SavvyCAN
点击查看免费下载

相关推荐

上一篇:ij-proxy 搜索工具面解析:JetBrains MCP 的主机透传、双 IDE 合并与容器内检索
下一篇:Crawlee表单处理:自动化填写和提交网页表单

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/14 2:06:28

Qt原生RSA加解密封装:绕过OpenSSL命令行的工程实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/14 2:06:22

无人自助拼豆系统全栈开发实战指南 核心功能实现与避坑经验分享

随着线下自助文娱业态的快速发展&#xff0c;无人值守的拼豆手工店正在成为商圈、社区的热门消费场景。用户无需店员接待&#xff0c;扫码即可解锁工位、领取材料包、自助完成拼豆创作&#xff0c;还可将未完成的作品寄存到共享柜中下次继续创作&#xff0c;整个流程完全自助化…

作者头像 李华
网站建设 2026/10/14 2:06:19

PyTorch实战:从教材PDF到可运行代码的工程化指南

简介&#xff1a;这是一份面向深度学习初学者与进阶开发者的经典英文原版教材《Deep Learning with PyTorch》PDF&#xff0c;由 Manning 出版&#xff0c;适合希望系统掌握 PyTorch 框架、从理论到工程落地完整学习的技术人员。资源包内共 1 个 PDF 文件&#xff0c;压缩包约 …

作者头像 李华
网站建设 2026/10/14 2:05:35

LTspice中文快速键一览表:从入门到肌肉记忆的键位指南

简介&#xff1a;这份LTspice中文快速键一览表面向电子技术与电磁学领域的电路设计初学者和仿真工程师&#xff0c;帮助解决软件操作不熟练、快捷键记忆零散、仿真分析效率低等问题。资源以PDF形式呈现&#xff0c;压缩包内共1个文件&#xff0c;大小约385KB&#xff0c;内容围…

作者头像 李华
网站建设 2026/10/14 2:05:22

华为AI大赛赛题拆解:缺陷检测、细粒度识别与Agent的工程实战

简介&#xff1a;第六届中国研究生人工智能创新大赛华为专项赛题详情以docx格式呈现&#xff0c;篇幅紧凑但信息完整&#xff0c;适合报名参赛的AI方向研究生及指导教师研读。文档正文包含两个典型赛题&#xff1a;其一是基于有限小样本的未知无规则缺陷图像检测&#xff0c;强…

作者头像 李华