一、背景
信号处理的“银弹”总是口口相传,不方便新同学快速学习。
二、目的
通过本文总结大部分信号处理相关最佳实践**,**帮助大家规避Bug,提高代码质量。
三、名词解释
-
什么是FD、FR、SC**FD:Function Design功能设计,类似PRD,主要描述功能场景。**例如:当用户点击舒控”AUTO”,需要执行风量自动、吹风模式自动等。FR:**Function Realization功能逻辑实现,主要是将FD描述的功能进行拆解,把每个SC需要做的逻辑拆解分配。例如:热管理SC: 接收AUTO信号,计算并发送对应风量、发送风量自动信号,计算并发送对应吹风模式,发送吹风模式自动信号,发送AUTO状态ON。 座舱SC:显示对应风量和风量AUTO图标等SC:System Component design系统需求设计,主要是落实FR。**整车需求开发链路是:FD➝FR➝SC➝ECU
❗ 注意 如果遇到SC和PRD不一致的情况,需要及时拉齐,优先以SC为准。
-
整车网络拓扑
缩写 中文名称 英文名称 配置 DCD 座舱控制单元 Digital Cockpit Domain 全系 VCCD 中央控制单元 Vehicle Central Control Domain ADD 智驾控制单元 Autonomous Driving Domain T-BOX 车载通信模块 Telematics Box
MS11
MS11整车网络拓扑V3.0-20230426.pdf
- 什么是上行信号&下行信号?从DCD发出的信号,称作下行信号;DCD接收的信号,称作上行信号。上行信号更新UI,下行信号控车。
- 什么是DBC文件?
DBC是DataBase Can的缩写,是CAN的数据库文件,该文件定义了整车CAN忘了各个节点控制器的通讯规则,可以理解为Android的AIDL文件。在测试过程中,可以配合PCAN和CANoe来使用,用于模拟和对手域通讯。
DBC文件格式说明
- 报文格式:
BO_ message_id message_name ':' message_size transmitter {signal} ;BO_ 839 VCCD_DCDCANFD_0x347: 32 VCCD
BO_ 929 DCD_DCDCANFD_0x3A1: 32 DCD**BO_ :**固定字符串,表示报文,可以理解为一组CAN信号的集合
**message_id:**报文ID 无符号正整数
**message_name:**报文名字
**message_size:**数据帧大小 CANFD最多支持64字节,CAN最多支持8字节
**transmitter:**报文发送者
- 信号格式:
signal = 'SG_' signal_name multiplexer_indicator ':' start_bit '|'
signal_size '@' byte_order value_type '(' factor ',' offset ')'
'[' minimum '|' maximum ']' unit receiver {',' receiver} ;
signal_name = DBC_identifier ; 充/放电功率
SG_ VCUHVExtPortEgyTrfActPwr : 135|14@0+ (0.1,-819.1) [-819.1|819.2] "kw" DCD
过热保护触发温度设置
SG_ DCDOvrHeatProtectTempSet : 76|5@0+ (1,29) [29|60] "" VCCD**SG_:**固定字符串,表示单一CAN信号
signal_name:信号名称
**multiplexer_indicator:**普通信号 or 多路复用信号。详见:下方文档
**start_bit:**在当前报文的起始位置,bit
**signal_size:**信号所占bit
**byte_order:**大小端,0=Big endian,1=Little endian,小米汽车全部使用Big endian。
**value_type:**无符号 or 有符号( + 无符号,- 有符号 )
factor & offset:系数 & 偏移量,精度double,factor用于定义精度,offset用于定义最小值。
📌 上行:physical_value = raw_value * factor + offset 下行:raw_value = (physical_value – offset) / factor 例如: 上行信号VCUHVExtPortEgyTrfActPwr(充放电功率),最小值是-819.1,精度0.1kW 转换关系由MCU处理。
minimum & maximum:有效的physical_value最大值&最小值, 精度double
**unit:**单位,字符串
**receiver:**信号接收者
-
CAN信号层级:座舱MCU:负责和外域进行CAN信号通讯,处理例如:信号丢失10个周期、快三帧,Press信号的长按、raw_value和physical_value转换等。通过S32K3XX芯片对应的CANFD引脚进行CAN信号的收发。并通过SPI总线和8295芯片进行通讯。SoC QNX CarService:处理SPI总线的信号数据,进行业务处理,例如:CAN信号到CarPropertyValue的N→1 or 1→N处理,信号Value的Not_Available到CarPropertyValue.Status的映射等。然后通过prop_interface接入仪表,通过QacService提供给其他QNX侧应用。然后通过Android&QNX共享内存的方式,通过Google Protocol Buffer提供给Android CarService。Android CarService:透传QNX CarService的CAN信号给Android应用 ;对于支持频率发送的信号,可以在registerCallback中设置上报频率, 按频率发送 (速度,角度等),详见:信号接入指南
-
对手域与ECUECU CAL _V4.0 _20230327
-
对手域:VCCD、ADD等和DCD连接的控制器。
-
ZCU:区域控制器,是车辆中的节点,用于分割电气和电子架构,并充当整车物理区域内设备(各种传感器、外围设备和执行器)的所有配电和数据连接要求的控制器。例如:左区域控制器(LZCU)、右区域控制器(RZCU)
-
ECU:电子控制器(又称作电子控制单元或电控单元,英语:Electronic Control Unit)是汽车电子系统中用来控制电气系统、电子系统及汽车子系统的嵌入式系统。DCD、VCCD、LZCU也属于ECU。
-
❤️ 温馨提示 目前整车的架构是所有逻辑集中在VCCD中管理,区域控制器ZCU只负责配电和执行。
-
CANFD与CAN的区别CAN FD 是CAN with Flexible Data rate的缩写。主要区别对比:
CAN CANFD 传输速率不同 最大传输速率1Mbps 速率可变,仲裁比特率最高1Mbps(与CAN相同),数据比特率最高8Mbps 数据帧长度不同 最长8字节 最长64字节 帧格式不同 CANFD在CAN基础上新增了FDF、BRS、ESI位 ID长度不同 11bit 12bit
❤️ 温馨提示 MS11使用的是CANFD
四、CarProperty介绍
CarPropertyManager
TODO
CarPropertyValue
public final class CarPropertyValue<T> implements Parcelable {
private final int mPropertyId;
private final int mAreaId;
private final int mStatus;
private final long mTimestamp;
private final T mValue;
}- PropertyId:信号ID,多个CAN信号可以对应一个PropertyId
| MASK | 0xF0000000 | 0x0F000000 | 0x00FF0000 | 0x0000F000 | 0x00000FFF |
| [VehiclePropertyGroup](https://cs.android.com/android/platform/superproject/+/master:out/soong/.intermediates/hardware/interfaces/automotive/vehicle/2.0/android.hardware.automotive.vehicle-V2.0-java-shallow/android_common/xref/srcjars.xref/android/hardware/automotive/vehicle/V2_0/VehiclePropertyGroup.java) | [VehicleArea](https://cs.android.com/android/platform/superproject/+/master:out/soong/.intermediates/hardware/interfaces/automotive/vehicle/2.0/android.hardware.automotive.vehicle-V2.0-java-shallow/android_common/xref/srcjars.xref/android/hardware/automotive/vehicle/V2_0/VehicleArea.java) | [VehiclePropertyType](https://cs.android.com/android/platform/superproject/+/master:packages/services/Car/car-lib/src/android/car/VehiclePropertyType.java) | MiVehicleZone | N/A | |
| MiCar | SYSTEM 1 VENDOR 2 MICAR 6 | GLOBAL 1 WINDOW 3 MIRROR 4 SEAT 5 DOOR 6 WHEEL 7 BODY 8 | STRING 0x00100000 BOOLEAN 0x00200000 INT32 0x00400000 INT32_VEC 0x00410000 INT64 0x00500000 INT64_VEC 0x00510000 FLOAT 0x00600000 FLOAT_VEC 0x00610000 BYTES 0x00700000 MIXED 0x00E00000 | BODY 0x00001000 LIGHT 0x00002000 DOOR 0x00003000 HVAC 0x00004000 WINDOW 0x00005000 SEAT 0x00006000 DRIVING 0x00007000 ENERGY 0x00008000 WARNING 0x00009000 GUARD 0x0000A000 PERIPHERAL 0x0000B000 | |
PropertyId和CAN信号对应关系:DCD车辆数据服务-信号列表
- AreaId:区域Id,用于区分同一PropertyId信号的不同区域
| Area | Area value Enum |
|---|---|
| WINDOW | VehicleAreaWindow |
| MIRROR | VehicleAreaMirror |
| SEAT | VehicleAreaSeat |
| DOOR | VehicleAreaDoor |
| WHEEL | VehicleAreaWheel |
| BODY | MiVehicleAreaBody |
例如:出风口开关
| PropertyId | 信号名称 | AreaId | CAN信号 |
| 0x65404113 | 主驾出风口1 | SEAT_ROW_1_LEFT | 上行:HvacFirstLeVga1OnOffSt 下行:DCDFirstLeVGA1OnOffSet |
| 主驾出风口2 | SEAT_ROW_1_LEFT | SEAT_ROW_1_CENTER | 上行:HvacFirstLeVga2OnOffSt 下行:DCDFirstLeVGA2OnOffSet | |
| 副驾出风口1 | SEAT_ROW_1_RIGHT | SEAT_ROW_1_CENTER | 上行:HvacFirstRiVga1OnOffSt 下行:DCDFirstRiVGA1OnOffSet | |
| 副驾出风口2 | SEAT_ROW_1_RIGHT | 上行:HvacFirstRiVga2OnOffSt 下行:DCDFirstRiVGA2OnOffSet |
- Status:
public static final int STATUS_AVAILABLE = 0;
public static final int STATUS_UNAVAILABLE = 1;
public static final int STATUS_ERROR = 2; // 目前没有用到
public static final int STATUS_TIMEOUT = 4;
public static final int STATUS_TIMEOUT_UNAVAILABLE = STATUS_UNAVAILABLE | STATUS_TIMEOUT;-
Value:信号的值,泛型类型。
-
Timestamp:Android的CarService收到上行信号的时间。通过SystemClock#elapsedRealtimeNanos获取。
CarPropertyConfig
TODO
五、最佳实践
- 信号类UI如何显示?
答:上行信号的Value和Status共同进行UI显示。
- 什么是UI先行 & 超时回弹?
💡 最佳实践 UI先行: 由于CAN信号从DCD发送到对手域,经过对手域处理后,再通过CAN信号返回给DCD,这个过程往往比较耗时(大约150ms),为了更好的用户体验,需要UI根据下一状态先行切换。 超时回弹: UI先行后,2秒内未确认UI,回滚到原状态。
❤️ 温馨提示 出现UI先行 & 超时回弹的前提是需要有下行信号,仪表类信号没有UI先行或超时回弹。
- 哪些下行信号不需要超时回弹?
💡 最佳实践 Press(btn软按键)信号不需要超时回弹,例如:座椅的高低、前后、靠背角度调节,由于上行信号(DrvrSeatHozlMotPosn)和下行信号(DCDDrvrHozlAdjHmiReq)是分开的, 对于超时逻辑,下行信号与上行信号分开,在下发Press信号时,启动计时器;
- 当2s内收到对应上行信号,应该把下行信号计时器移除;
- 当2s内没有收到对应上行信号,应该做个映射,以对应上行信号进行超时回弹处理;
- 信号不可用是什么?
- 信号丢失
信号丢失 > 10个周期
-
不可用例如:例如:PwrModVld和SteerWhlHeatFcnAvlSts
- Value值为“Not_Available”,车控类预留,几乎不会上报,但是我们也要处理。
🏅 小知识 从“空调系统开关”信号,我们可以看出,上行的Value定义和下行信号Value定义可以不一致。
-
xxxVld 和 xxxAvlSts
🏅 小知识 Vld用于表示XX信号数据有效性,比如电源模式有效性(PwrModVld),挡位有效性(VCUGearLvrForDispVld);AvlSts用于表示车控XX信号的可用性,一般会伴随“不可用原因”信号,例如:方向盘加热可用性(SteerWhlHeatFcnAvlSts)和方向盘加热不可用原因(SteerWhlHeatFcnNotAvlRsn)。
| 当前Value | 信号是否丢失 | Status |
|---|---|---|
| Not_Available¹ | 丢失 | STATUS_TIMEOUT_UNAVAILABLE |
| 正常值 | 丢失 | STATUS_TIMEOUT |
| Not_Available¹ | 未丢失 | STATUS_UNAVAILABLE |
| 正常值 | 未丢失 | STATUS_AVAILABLE |
Value值为“Not_Available” 或 xxxVld为无效 或 xxxAvlSts为不可用
💡 UI处理最佳实践 因此在信号处理中不仅仅要处理对应的值,也要处理信号的Status。具体处理细节请遵循SC&PRD
[飞书 Mindnote 嵌入块] (token=B1jXbqshgmBhqSneWYccDKG2n0g) — 飞书原生 mindnote 结构,无法转 markdown,请前往 原文 查看
- Not_used & Reserved 类信号如何处理?由于信号的signal_sizes是信号所占的bit,对应的Value的取值范围为,因此会有一些bit没有用到或作为保留。
💡 最佳实践 绝大部分的Not_used & Reserved都被QNX CarService过滤掉了。
- 组合信号如何处理?
💡 最佳实践 由于组合信号可能涉及多个报文分组的上行信号,会有先后顺序或信号丢失的情况,因此需要对全部信号进行缓存,当某个信号更新时,更新对应信号,并将所有信号的结果进行组合更新UI。 对于非常复杂的组合信号,可以让系统工程老师提供《信号和UI对照表》,例如:充放电状态UI显示—供理解
参考代码:
int signalAVal = 0, signalBVal = 0;
boolean signalAEnable = false,signalBEnable = false;
public void onChangeEvent(CarPropertyValue value) {
int propertyId = value.getPropertyId();
switch(propertyId) {
case SIGNAL_A:
signalAVal = (int) value.getValue();
signalAEnable = VehiclePropertyUtil.isAvailable(value);
refreshUi();
break;
case SIGNAL_B:
signalBVal = (int) value.getValue();
signalBEnable = VehiclePropertyUtil.isAvailable(value);
refreshUi();
break;
}
private void refreshUi() {
int ret = signalAVal + signalBVal;
bool enabled = signalAEnable && signalBEnable;
}
}💡 最佳实践 如果组合信号更新同一个ICON的不同状态,则需要分开更新,例如:座椅加热通风,一个ICON有AUTO和State两个信号控制状态,则需要分别更新,而不是使用缓存值。 原因:当下行State-3,UI会现行到3,这时如果Auto信号变化时,如果getStateValue()则使用的是旧缓存值,如此就打破了UI现行的逻辑,此时就出现UI先行到了3,但是又刷新到了0,等真正3上来了又变成了3的闪跳现行。
public void onChangeEvent(CarPropertyValue value) {
int propertyId = value.getPropertyId();
switch(propertyId) {
case SIGNAL_A_STATE:
refreshUi(value, null);
break;
case SIGNAL_A_AUTO:
refreshUi(null, value);
break;
}
private void refreshUi(CarPropertyValue state, CarPropertyValue auto) {
if (state != null) {
// 刷新State
}
if (auto != null) {
// 刷新Auto
}
}
}-
什么是Seekbar的跟手下发&抬手下发?示例:空调风量设置、氛围灯颜色选择、电动出风口XY坐标设置、能量管理充放电限值设置。舒控出风位置:
- 跟手下发:滑动过程中下发信号。
优点:滑动中可多次下发信号,车辆状态可以实时更新 缺点:处理不当容易造成Thumb抖动
用于对实时性要求高的信号,这类信号会通过车辆状态给用户带来实时的反馈,用户跟着感觉调节,调节到满意的位置即可松手,例如:空调风量设置、氛围灯颜色选择、电动出风口XY坐标设置。
💡 最佳实践 开始滑动时停止上行信号对UI更新(上行信号可持续监听),以免发生抖动。滑动中持续下发信号,下发最后一个信号后开始2秒计时,如果2秒内没有信号下发,第2秒主动调用getProperty信号用于校准,然后恢复上行信号对UI更新。
- 抬手下发:抬手后下发一次信号
优点:不会造成抖动(忽略短时间内多次滑动的情况) 缺点:无法在滑动中实时改变信号
用于对实时性要求不高的信号,这类信号不会给用户带来实时的反馈,例如:能量管理充放电限值。
- 自定义”类SeekBar”控件的无极滑动和分段吸附滑动有什么区别?
- 无极滑动:
优点:滑动体验丝滑 缺点:处理不当容易造成细微抖动
💡 最佳实践 上行返回信号进行UI确认前,先判断当前的UI位置四舍五入后是否和上行信号值相等,如果相等,保留Thumb当前位置即可,反之则更新UI。
❤️ 温馨提示 滑动到两个整数数值之间时,下发逻辑按照 四舍五入 或 下取整 或 上取整,请根据SC or 产品文档描述决定。
- 分段吸附滑动
优点: 信号处理简单 缺点:滑动有些许顿挫感
- SC/PRD描述的逻辑应该应用层实现吗?
SC/PRD中有一些逻辑,例如舒控PRD:当用户点击”A/C”、改变风量、改变出风模式时退出”AUTO”;在下电时,AUTO模式需要进行记忆。这些其实是对手域的逻辑,应用层对于信号的处理绝大部分是“显示”和“控制”,极少部分需要做逻辑兜底处理。
💡 最佳实践 一定要和系统工程、产品达成一致该功能由对手域实现,DCD不需要做兜底处理后,结论同步测试。防止需求遗漏。
- 有显示和设置信号功能的Dialog(二级页)如何处理?
预约出发时间CAN信号:12:00
打开Dialog时Value是否跟随信号?
例如:充放电-预约出发时间设置Dialog,当前信号为12:00,设置信号11:00,点击确定关闭Dialog并下发信号,在信号回弹之前立即打开Dialog,此时会有两种选择:
- Dialog跟随信号:此时TimePicker显示,12:00
- Dialog跟随外部显示:此时TimePicker显示,11:00
💡 最佳实践 建议跟随外部显示,这样符合UI先行原则,具体情况需要和产品确认。
Dialog是否监听信号?
例如:充放电-预约出发时间设置Dialog,当前CAN信号为12:00,设置信号11:00,点击确定关闭Dialog并下发信号,在信号回弹之前立即打开Dialog,并快速设置信号为10:00,此时会有两种选择:
- Dialog监听信号:此时看到,TimePicker被拨到10:00后,TimePicker快速超时回弹到了12:00。
- Dialog不监听信号:外部文本信号回弹到12:00,Dialog TimePicker时间不变(10:00)。
💡 最佳实践 不建议监听信号,只显示信号的“快照”即可,具体情况需要和产品确认。
- 多Tab快速点击如何避免闪跳?
核心逻辑&处理方式类似SeekBar跟手下发。
- 信号缓存与过滤的作用是什么?
💡 最佳实践 一些底层信号会频繁的上报,但是内容更新的频率不高,为了防止UI每次刷新相同的内容,我们可以做一层缓存层,缓存对应的信号,并根据value、status、areaId等信号是否变化进行相应的缓存&UI刷新 或 忽略。
- 复杂信号的合并
💡 最佳实践 由于一些业务逻辑要求,需要一些信号组合上报并显示对应的UI。这样会增加业务的复杂程度。对于多个业务通用且比较复杂的信号组合,我们可以和系统工程老师协商,合并成单一信号,从而简化业务开发逻辑。
例如:
- 仪表的组合信号 ➝ TT协议
- 充电口盖状态ChrgLidSts & ChrgLidSoftBtnDisp ➝ ChrgLidCurSts
- 单按钮快速点击
TODO
循环模式和循环模式自动的情况,需要一起不监听。
六、信号分类
- 什么是配置字?用于标识车辆的**一个可变项目。**存储在MCU的EEPROM中,QNX端不做存储,系统上电时每次动态从MCU端获取。
例如:
| 英文名称 | 中文名称 | 值 | 信号 |
|---|---|---|---|
| High Voltage Battery Chemical Type | 高压(动力)电池类型 | 0x1: lithium iron phosphate battery 磷酸铁锂电池 0x2: Ternary lithium battery 三元锂电池 | HvBattChemicalConfig |
💡 最佳实践 对于配置字类信号,无需进行监听,在应用(模块)启动时主动获取一次即可。对于后续购买类配置,生效需要重启DCD(应用),因此启动时主动getProperty即可满足。
整车配置系统介绍-2022215.pptx
- 什么是内部信号?用于DCD内部通讯的信号,发送方和接收方都是DCD,例如:公里和英里切换信号DstUnitDisp。反之如果发送方或接收方是外域的信号,称作外域信号。
- 机械类信号如何处理?
机械类信号由于机械本身的限制,存在“正在运动”的中间状态。
-
按钮类机械信号,例如:充电口盖打开与关闭、外后视镜的折叠与展开。
💡 最佳实践 由于中间状态时间较长,UI状态不能先行到下一状态,因此需要给用户一个“信号处理中”的提示,例如:Loading动画,文案提示等。
-
SeekBar类机械信号,例如:空调风量设置。风量滑动条特殊需求
💡 最佳实践 频繁的高速滑动SeekBar(下发信号)会加快机械结构的磨损,甚至会导致机械故障和损坏。因此,对于机械类信号,我们应该尽量控制信号的下发频率,在不影响用于体验的前提下,通过某种策略进行采样。
🏅 小知识 对于一些机械组件,自身有一套防玩机制,多次开关会触发“控制不可用”状态原因为“防玩模式禁止XXX”。例如:充电口盖开启&关闭、外后视镜展开&折叠。
-
Telltale灯(TT灯)是什么?在MS11中,座舱MCU按照一定频率将整车的多个CAN信号进行组合计算,然后将计算结果按照TT协议编码成一个ByteArray,再通过一个PropertyId为0x61709149的CarPropertyValue上报给上层应用。从而控制TT灯的状态(点亮、熄灭、闪烁),目前TT灯已经在中控屏StatusBar、仪表(QNX)、HUD、功能安全校验、备份渲染中使用。TT协议分为动态协议(2个Bytes)和静态协议(1个Byte)两种。TT灯解析程序,用于将数组解析成可读的TT协议,极大的提高了Bug分析效率:
🏅 小知识 Telltale灯,以下简称TT灯,即警告灯,用于提醒操作者车辆中存在潜在问题或需要注意的事项。
| 数组Index | 0 | 1 | 2 | 3 | 4 | 。。。。 | 75 | 76 | 。。。。 |
| 说明 | 点亮的动态灯个数 | 动态信号A | 动态信号B | P挡 | R挡 | ||||
| Id | payload | Id | payload | payload | payload | ||||
为了和CarPropertyValue中的Value进行区分,TT协议中对应信号值我们称为payload。
👍 MCU的工作:
- 通过对各种组合信号(功能信号和电源模式信号)进行汇总,控制TT灯的状态(点亮、熄灭、闪烁、呼吸动画)
- TT灯位置排序
- 功能安全灯的校验
- 处理TT灯的信号超时以及自检逻辑
💡 最佳实践 在UI层面上TT灯的状态分为四种:显示、隐藏、闪烁、呼吸动画。 显示:View.VISIBLE 隐藏:View.GONE 闪烁:按照一定频率切换View.VISIBLE & View.INVISIBLE,注意这里不是GONE,原因见下图。 呼吸动画:Alpha动画 0⇋1 交替变化。
| TT灯协议 | TT灯解析程序 | |||
| E4 | [TT灯方案 V01](https://mi.feishu.cn/docx/K9kwdLo7loJ9JwxHb8hc3a01nzf) | [MS11_VehicleCore_SPI_Protocol](https://mi.feishu.cn/sheets/NVsLsDglEhFvXFt0myKcNXTsnRb) | [E4-python脚本可视化解析TT协议数组](https://mi.feishu.cn/docx/Xtr1ds1kVo4nNGxDwnMcGwDjn9c) | [TT灯解析程序Gerrit](http://gerrit.auto.mioffice.cn/admin/repos/cockpit/Plugins) |
| E4U1 | [TT灯方案 V02 E4U1](https://mi.feishu.cn/docx/Ecund8owyohtwmxsS26coFctnud) | [E4U-python脚本可视化解析TT协议数组](https://mi.feishu.cn/docx/BOVSd6dxUoWg0gxOlfccwzbZnic) | ||
-
TT灯与法规由于TT灯涉及车辆的安全性,因此国标对TT灯的图案、颜色等行了严格规定,详见:
-
什么是Press信号?
Press信号,又被称为软按键 或 Btn类信号,这种信号通常用于复杂的状态切换类信号,例如:循环模式。或用于数值 +/-类信号,例如:座椅前后调节、风量+/风量-等。Press信号一般有对应的上行信号用于表示结果。
💡 最佳实践 Press信号由于“下一状态”未知,因此无法进行UI先行,而且Press信号仅仅用于下行控车,因此也不存在超时回弹。在下发此类信号时应该使用无回弹计时器的setProperty下发。 由于无法进行UI先行,需要针对相应上行信号的响应时间进行评估。如果对应上行信号响应较慢,会产生点击后长时间无反应的体验问题。可以通过添加按钮按压动效,减少无法UI先行带来的体验问题。
- CAN E2E作用是什么?
🏅 小知识 E2E Protection,全称End to End Protection,即端到端保护机制的简称。在该机制中,发送端和接收端之间的信息受到保护,且对传输的信息进行一致性和完整性的校验,不受信息传递过程中协议转换或者路由情况的影响。
- 信息的重复发送 (Repetition of Information),相同的信息被收到了多次
- 信息的丢失 (Loss of Information),整条或者信息的一部分在通信过程中丢失
- 信息的延迟 (Delay of Information),接收信息的时间异于期望的时间
- 信息的插入 (Insertion of Information),多余的内容被插入到信息中
- 假冒的或者不正确的寻址 (Masquerade or Incorrect Addressing of Information),假冒的发送者发送未认证的信息被接收端接受,或者正确的信息被错误的接收端接受
- 信息顺序错误 (Incorrect Sequence of Information),数据流中的信息顺序错误
- 信息破损 (Corruption of Information),信息的内容被篡改
- 向多个接收端发送非对称信息 (Asymmetric information sent from a sender to multiple receivers),接收端收到的数据不一致
- 仅部分接收端收到发送者的信息 (Information from a sender received by only a subset of receivers
- 阻塞通信通道 (Blocking access to communication channel)
-
什么是SOA信号?基于以太网的 SOA 架构传输的信号,VCCD/DCD/Tbox/ADD 都部署 DDS 协议栈,为跨域间通信提供服务接口。 例如:智驾SR,ADD收集各种传感器的数据,通过计算后把坐标和物体类型通过DDS传给DCD,智驾Unity根据坐标渲染对应3D模型。下图红框内的,即,ADD & DCD 的 ETH
七、工具介绍
- CAN工具简介:
- CANoe(CAN open environment)
CANoe是Vector Informatik所开发的软体开发及测试工具。主要用在汽车制造商以及电子控制器(MCU)供应商,可用在电子控制器网路或个别电子控制器的开发、分析、模拟、测试、诊断及启动。可以适用于许多的车用网路协定,因此适合用在燃油车、油电混合车及电动车电子控制器的开发。其中的模拟及测试机能是由CAPL程式语言进行的。
CANoe -VN5620
👍 优点
- 可以进行CAN信号回灌,用于快速定位排查问题,例如:回灌能耗曲线等复杂CAN信号
- 可以测试下行信号
- 可以无缝切换各个信号值
- 图形界面强大,可以自定义信号发送面板
- 可以轻易模拟信号丢失
- 对E2E信号支持稳定
👎 缺点 贵!
PCAN-USB FD可以将CAN和CAN FD网络的报文通过USB连接到电脑,用于监控CAN网络。也可以发送、保存、过滤CAN报文。电气隔离达到500V。
座舱测试老师开发:车机助手使用手册
- Mock信号
Mock value
- 可以不通过CAN模拟器,直接修改CarPropertyValue。
- Mock Not_Available
通过改变VehiclePropertyUtils.isPropertyAvailable进行mock
-
获取车辆拨杆CAN Log
- 左侧拨杆向自己拉8秒
- 记住当前时间和车辆编号
- 向测试or系统工程老师要CAN Log
八、PRD/SC/Figma 评审CheckList
❤️ 温馨提示 Level 1:评审时现场向系统工程、产品、设计提问。 Level 2:评审前看PRD/SC/Figma,把相关问题发给系统工程、产品、设计。评审会进行现场解答。 Level 3:培养系统工程、产品、设计,养成思考如下问题的能力。
- 什么类型的信号?控车、显示、仪表?
- 上行 or 下行的信号?
- 如果是控车信号,使用Set信号还是Press信号?
- SeekBar类组件,抬手下发还是跟手下发?
- 信号丢失或value==Not_Available,UI如何显示?
- 是否是机械信号?是否有中间态?Figma是否有Loading动效或相关提示?
- 信号是否过于复杂可以合并?
- 需要做超时回弹吗?
- 显示浮点数?显示几位小数?四舍五入 or 下取整 or 上取整?
- 时间类信号是否跟随系统时间单位制式?12小时制 or 24小时制?
- 有没有AreaID的概念,如果有用那个AreaID?
- 快速点击会不会导致闪跳?
- PRD/SC中是否有特殊逻辑,特殊逻辑是对手域处理吗?
- Dialog是否要监听信号的上报,是否支持超时回弹?
- 是否支持单位切换?例如:胎压的三种单位,bar、kPa、psi
- 这个信号有特许权限吗?申请特许权限了吗?配置特许权限白名单了吗?
- Enable==false时候是否保持原值?
- UI的设计是否有覆盖边界情况?边界情况如何显示?
- 上行信号收到超过边界外的Value如何兜底?
- UI状态和组合信号如何对应?
- 配置字高、低配如何显示该功能?
- 信息展示类信号Figma设计时是否考虑了文案过长的显示不全的问题?
- 是否存在同一界面两个UI控件同时显示A信号,其中一个UI修改A信号,这时候另一个UI会延时更新UI。
九、注意事项
❤️ 温馨提示 新增添加信号,需要检查对应的权限,是否已经添加到AndroidManifest.xml,对应的权限是否已经配置到特许权限白名单中,否则会导致应用or系统崩溃。
十、未来计划
- 和姚鹏老师沟通做一个信号“快照”功能,打印在bugreport里边,用于快速分析线上问题。
- 计划后续做一个“信号集成SDK”,包含一些通用信号逻辑的处理,方便新增业务快速、低成本承接信号类需求。
十一、结束语
本文写到这里只是体现了“信号处理”技巧的冰山一脚。仅仅作为抛砖引玉,让我们共同维护这篇文档,把更多“信号处理”技巧分享给大家。
兵无常势,水无常形;能因敌变化而取胜者,谓之神。——《孙子兵法·虚实》
希望大家在处理信号类需求的时候,能够像战神一样,战无不胜,一往无前!
十二、感谢
感谢各位老师的细心解答:
@丁艳玲 @曹旭 @康森源 @汪杨杨 @王建洲 @姚鹏 @张佃伦
十三、Q&A
更新记录:
| 更新内容 | 更新时间 | |
|---|---|---|
| V1.0 | 初版 | 2023.06.15 |
| V.1.1 | 添加车辆拨杆获取CAN Log | 2023.07.03 |