21、车载诊断与日志:让系统学会“说话”

各位同学,今天我们来聊聊车载系统里一个特别重要的能力——诊断与日志。说白了,就是让系统在出问题的时候,能清楚地告诉我们“我哪里不舒服”。

我在做IVI项目时,遇到过最头疼的事不是功能做不出来,而是车跑在路上,用户报了个bug,我们却完全不知道发生了什么。那时候我就意识到,诊断和日志系统,就是车载开发的“黑匣子”。

车载诊断系统:OBD-II 与 UDS

先说说两个基础概念:OBD-II 和 UDS。

OBD-II(On-Board Diagnostics II)是车载诊断的“老前辈”。它最早是为了排放检测而生的。你想想看,每辆车都要过环保检测,OBD-II就是那个标准接口。它定义了一组标准诊断故障码(DTC),比如P0300表示“检测到随机/多缸失火”。

UDS(Unified Diagnostic Services)则是更现代、更强大的诊断协议。它基于ISO 14229标准,功能比OBD-II丰富得多。UDS不仅能读故障码,还能读写数据、执行例程、刷写固件。说白了,OBD-II是“体检报告”,UDS是“全套体检+治疗”。

关键区别:

  • OBD-II:强制标准,主要用于排放相关,协议简单
  • UDS:可选但广泛使用,覆盖整车所有ECU,功能强大

我个人习惯,在Android Automotive项目中,UDS用得更多。因为我们需要诊断的不只是发动机,还有信息娱乐系统、空调、座椅等等。

CarDiagnosticService 与诊断数据获取

在Android Automotive里,诊断数据的获取主要通过 CarDiagnosticService。这个服务是Android汽车服务的一部分,它封装了底层的诊断协议,向上层应用提供统一的API。

来看一个简单的例子,获取车辆故障码:

// 获取CarDiagnosticManager
CarDiagnosticManager diagnosticManager = 
    (CarDiagnosticManager) car.getCarManager(Car.DIAGNOSTIC_SERVICE);

// 注册故障码监听
diagnosticManager.addDiagnosticListener(
    new CarDiagnosticManager.DiagnosticListener() {
        @Override
        public void onDiagnosticEvent(DiagnosticEvent event) {
            // 处理诊断事件
            Log.d("Diagnostic", "故障码: " + event.getDtc());
            Log.d("Diagnostic", "严重级别: " + event.getSeverity());
        }
    }
);

嗯,这里要注意:CarDiagnosticService 需要系统级权限。普通应用是拿不到的。我在项目中就踩过这个坑——写了个诊断App,结果一直报权限错误。后来才知道,只有系统应用或者有签名权限的应用才能访问。

避坑指南:

我曾经在调试时发现,某些诊断事件在模拟器上收不到。后来查了半天,发现是模拟器没有模拟对应的CAN总线信号。所以,诊断功能的开发,最好在实车或HIL(硬件在环)环境下进行。

日志系统:logcat、dmesg、车载日志

诊断是主动的,日志是被动的。但两者缺一不可。

logcat 是Android开发者的老朋友了。它主要输出应用层和框架层的日志。在车载开发中,我习惯用 logcat -b all 来查看所有缓冲区的内容,包括events、system、main等。

dmesg 则是内核日志。当系统出现死机、重启、驱动加载失败等问题时,dmesg往往是第一手线索。我记得有一次,车载蓝牙死活连不上,logcat里什么异常都没有。但dmesg里明确写着:btusb: firmware loading failed。嗯,问题一下就定位了。

车载日志 是更专业的说法。在量产车上,日志需要持久化存储,并且要有轮转机制。你不能让日志把存储空间撑爆了。我建议的配置是:

日志类型存储路径保留策略
应用日志/data/log/app/保留7天,单文件最大10MB
系统日志/data/log/system/保留30天,单文件最大50MB
内核日志/data/log/kernel/保留90天,单文件最大100MB
诊断日志/data/log/diag/保留180天,单文件最大200MB

警告: 日志不能无限制增长。我曾经见过一台测试车,因为日志把/data分区写满了,导致系统无法启动。从那以后,我每次都会加上日志大小限制和自动清理机制。

远程诊断与故障排查

车卖出去之后,问题怎么排查?总不能每次都把车开回工厂吧。这时候就需要远程诊断了。

远程诊断的核心思路是:车端采集数据 → 云端存储分析 → 远程下发诊断指令。

我参与过一个项目,用户反映导航偶尔会卡死。但这个问题复现概率极低,工程师跟车跑了一周都没抓到。后来我们上了远程日志上传功能,用户遇到问题时一键上传日志。结果发现是某个地图数据文件损坏导致的。你看,没有远程诊断,这个问题可能永远查不出来。

远程诊断的典型流程:

  1. 车端检测到异常(如DTC触发)
  2. 自动上传关键日志到云端
  3. 云端分析,生成诊断报告
  4. 必要时,远程下发诊断指令(如读取特定数据、执行自检)
  5. 车端执行并返回结果

这里有个技术细节:远程诊断的通信协议,我建议使用MQTT。它轻量、支持双向通信、而且有QoS保证。HTTP虽然简单,但在弱网环境下表现不如MQTT。

核心要点总结:

  • OBD-II是基础,UDS是进阶,两者都要掌握
  • CarDiagnosticService是Android Automotive的诊断入口
  • logcat看应用层,dmesg看内核层,车载日志要持久化
  • 远程诊断是量产后的“救命稻草”
车载诊断与日志系统架构 OBD-II / UDS 系统日志 应用日志 CarDiagnosticService / logcat / dmesg 本地存储(轮转日志) 远程诊断(MQTT/云端) 故障排查 / 数据分析 远程OTA / 主动服务

最后说一句:诊断和日志,平时你可能觉得它们不重要。但一旦出了问题,它们就是你最可靠的伙伴。我见过太多开发者在项目初期忽略日志系统,结果到了路测阶段手忙脚乱。别犯同样的错误。


公众号:蓝海资料掘金营,微信deep3321