zhuanzai:https://www.cnblogs.com/yao-zhang/p/10329922.html

为满足项目过程中不同阶段绝大部分测试需求,更方便快捷构造测试场景,支持异常场景测试。更早介入,不依赖周边ECU的稳定情况,专注于被测ECU。更经济,不加油,不充电,时间节省,物料节省等维度考虑。我们需要一个建设测试台架至少可覆盖实车上80%的测试场景需求。

目标任务分解

1、车内网络模型建立

模拟车内网络通信模型,各节点信号仿真

2、业务关联的ECU仿真

封装ECU之间的业务交互逻辑,车身控制器,仪表台模拟等

a)每个ECU的逻辑都是随CANoe启动,激活CAN通信;

b)根据PEPS电源信号状态决定该ECU的活跃状态;

c)ECU 根据具体业务处理总线上的请求;

d)设计仿真器的ECU则根据信号变化情况,更新仿真器的状态

CAPL编程实现

1、环境变量

为实现控制面板输入输出与信号同步,实现仿真器的状态更新,先定义与信号成映射关系的环境变量。环境变量的定义主要根据各ECU的相关信号与业务的关联度决定。基本上与T业务挂钩的信号都应该设置相应的环境变量,监控信号变化,实时更新仿真器的状态。

2、各ECU通用代码块

存储一些全局变量,日志记录等,各ECU可包含此文件调用

variables
{// 报文发送周期, 单位msconst int varCycTime10 = 10;const int varCycTime20 = 20;const int varCycTime50 = 50;const int varCycTime100 = 100;const int varCycTime200 = 200;const int varCycTime500 = 500;const int varCycTime1000 = 1000;// varCarType车型定义, 0=纯油, 1=纯电, 2=混动, others=error// 字母代码 AFV=纯油, EV=纯电, HEV=混动(不区分直插式和充电桩式)// 全局LOGlong mTrace = 0; //severitydword INFO = 1;dword WARN = 2;dword ERROR = 3;// 鉴权秘钥byte varESKCode[10][8] = {//。。。略}; // varCarCode 标记当前被测车型, 用于选择调用正确的鉴权码int varESKNumber;// 记录当前电源模式,0=OFF; 1=ACC; 2=ON; 3=reserved; 4=start; 5,6,7=reservedint varPowerMode=0;int lastPowerMode=0;// 发动机状态int varEngineStatus;//总线报文管理,0=停发, 1=启动int varNM;// 远程控制请求中,启动发动机的时间int varRmStartTime;// 远程控制请求中,启动发动机的时间长度 分级int varRmStartTimeLvl; 0=No Req; 1=3min; 2=5min; 3=8min; 4=10min; 5,6,7=reserved
//  // 防盗报警定时器
//  timer BCM_ATWS_timer;//车速int varVelSpeed;//标记发动机是否已启动int IsEngineWorking = 0;
}/***********************************************************
* description  : 全局日志记录函数
* parameter    : None
* creation date: 2018/10/26
* author       : xxx
* revision date:
* revision log :
* modifier     :
***********************************************************/
void InitLogging()
{mTrace = writeCreate("Logging");writeConfigure(mTrace,1024*1000,1,"..\\Proj\\Log\\write.txt");writeclear(1);
}

3、ESC封装车速信号,处理行车过程中自动落锁的逻辑

此处详尽展现代码实现段落开始处所描述的四点逻辑,后续ECU只展现具体的业务处理,不在代码展示中继续保留a)&  b),或 d)

includes
{#include "ECUsVar.can"
}variables
{//本消息由ESC发出,包含ESC状态,车速、以及刹车板状态信号, 此处ID由我捏造为0x111message 0x111 ESC_Status; msTimer ESC_timer;
}on timer ESC_timer
{output(ESC_Status);setTimer(ESC_timer, varCycTime20);
}//车速
on envVar ESC_VehicleSpeed
{ float factor = 0.05625;int offset = 0;varVelSpeed = getValue(ESC_VehicleSpeed);//转换成仪表显示, KPHif(varPowerMode!=2){writeDbgLevel(1, "PowerMode=OFF,车速调节无效");ESC_Status.ESC_VehicleSpeed = 0;putValue(ESC_VehicleSpeed, 0);}else{if(varVelSpeed!=0) //置位发动机转速{writeDbgLevel(1, "点火状态,车速不为零,设置发动机转速");putValue(EMS_EngineSpeedRPM,3000);}else{putValue(EMS_EngineSpeedRPM,0);}if(varVelSpeed>25) //车速>25时,自动落锁{writeDbgLevel(1,"车速>25码,自动落锁");putValue(LockDoors, 1);}ESC_Status.ESC_VehicleSpeed = (varVelSpeed-offset)/ factor;}
}on envVar PEPS_PowerMode
{// 此处根据PEPS电源状态封装ESC在网络上的活跃情况(是否对外发送信号和处理总线上的请求)
}on start
{InitESCValue();ActiveESC();
}//初始化
void InitESCValue()
{varPowerMode = getValue(PEPS_PowerMode);//以下两行代码初始化ESC信号,此处略去其它很多信号,自填......putValue(ESC_VehicleSpeed, 0);ESC_Status.xxx=0;
}//激活
void ActiveESC()
{setTimer(ESC_timer, varCycTime20);
}
//去激活
void InactiveESC()
{cancelTimer(ESC_timer);
}

4、IPK实现同步系统时间

若你的车联网系统的标准时钟来自其它ECU,则以该ECU的时间为参考。这涉及判断T业务的实时性与有效性逻辑。(注意:我所用的CANoe 8.5.98的调用getLocalTimeString获取系统时间异常,我通过代码矫正了一下,11.0版本则不用矫正)

variables
{const h_offset = 0;//5; //时差const m_offset = 0;//5; //分差// IPK提供日期时间信息, 年月日,时分秒;500msmessage 0x222 IPK_DateTime;  //以下报文ID全由我捏造,可根据实际DBC中定义修改成相应ID// IPK提供纯电续航里程、平均电耗、瞬时电耗、油耗, 1000msmessage 0x223 IPK_Data;// 本消息由IPK发出,包含仪表的信息,100ms// 安全气囊控制器状态检查反馈,剩余油量,平均车速,手刹状态,保养提示报警,背光调节,机油压力低报警状态message 0x224 IPK_STS;// 本消息由IPK发出,包含总里程的信息,可续航里程,保养里程;1000msmessage 0x225 IPK_Odometer;msTimer IPK_Date_timer;msTimer IPK_ODO_timer;msTimer IPK_Sts_timer;//当前时间提示器, 用来核对TBOX系统时间是否正确timer DateRemanderTimer;// 存放时间的数组,当IPK负载不存在时,仿真实现。传递时间到TBOXlong tm[9];char t_canoe[26];char t_now[26];
}***********************************************************
* description  : 由IPK发出的系统时间,传递给TBOX同步此时间
* parameter    : None
* creation date: 2018/10/15
* author       : xxx
* revision date:
* revision log :
* modifier     :
***********************************************************/
on timer IPK_Date_timer
{output(IPK_DateTime);setTimer(IPK_Date_timer, varCycTime500);
}/***********************************************************
* description  : 由IPK发出的仪表盘信息
* parameter    : None
* creation date: 2018/10/15
* author       : xxx
* revision date:
* revision log :
* modifier     :
***********************************************************/
on timer IPK_Sts_timer
{GetSysTime();output(IPK_STS);setTimer(IPK_Sts_timer, varCycTime100);
}/***********************************************************
* description  : 由IPK发出的里程相关信息,可能会根据油车,混动,纯电,展示的信息不一致,根据DBC定义来实现
* parameter    : None
* creation date: 2018/10/15
* author       : xxx
* revision date:
* revision log :
* modifier     :
***********************************************************/
on timer IPK_ODO_timer
{output(IPK_Odometer);setTimer(IPK_AFV_ODO_timer, varCycTime1000);
}/***********************************************************
* description  : 获取当前PC时间,作为IPK时间发布到CAN线上
* parameter    : None
* creation date: 2018/10/15
* author       : xxx
* revision date:
* revision log :
* modifier     :
***********************************************************/
void GetSysTime()
{getLocalTimeString(t_canoe);getLocalTime(tm);// year since 1900; month from 0-11 IPK_DateTime.IPK_Year = tm[5]-100;IPK_DateTime.IPK_Month = tm[4]+1;IPK_DateTime.IPK_Second = tm[0];//以上API获取的时间比北京时间快6h 5minif(tm[2]>=h_offset) //24小时制{IPK_DateTime.IPK_Hour = tm[2]-h_offset; //减去快的6HIPK_DateTime.IPK_Day = tm[3];}else{IPK_DateTime.IPK_Hour = tm[2] -h_offset+24; //当时间跳到第二天凌晨,逆向+18IPK_DateTime.IPK_Day = tm[3] -1; // day-1}if(tm[1]>=m_offset) //处理分钟{IPK_DateTime.IPK_Minute = tm[1] -m_offset;}else{IPK_DateTime.IPK_Minute = tm[1] -m_offset + 60;//此时小时跨度要再减一小时IPK_DateTime.IPK_Hour = tm[2]-(h_offset+1); //减去快的6H and 跨时段1}//格式化当前时间戳snprintf(t_now, elcount(t_now),"%d/%d/%d %02d:%02d:%02d", tm[5]+1900, tm[4]+1, tm[3], IPK_DateTime.IPK_Hour,IPK_DateTime.IPK_Minute,tm[0]);
}
//log输出  提示作用
on timer DateRemanderTimer
{writeDbgLevel(1, "CANoe Time: %s", t_canoe);writeDbgLevel(1, "Now Time:%s", t_now);setTimer(DateRemanderTimer, varCycTime10);
}//激活IPK(当电源ON时,触发)
//去激活IPK(当电源OFF时,停发IPK报文)// 设置每次启动CANoe时,仪表盘的初值//电源模式变更时,处理IPK在总线上的活跃状态//以下代码举两个例子描述,具体信号的变化,呈现在控制面板上的为物理值。其余信号可自己根据样板添加
//平均油耗 L/100Km
on envVar IPK_AverageFuelConsumption
{int temp;//偏移量与精度值float factor = 0.01;int offset = 0;temp = getValue(IPK_AverageFuelConsumption);IPK_Data.IPK_AverageFuelConsumption = (temp-offset)/factor;
}//平均电耗 KWH/100km
on envVar IPK_AveragePowerConsumption
{int temp;//偏移量与精度值float factor = 0.1;int offset = -99.9;temp = getValue(IPK_AveragePowerConsumption);IPK_Data.IPK_AveragePowerConsumption = (temp-offset)/factor;
}

5、车身模拟器,BCM+EMS

EMS仿真实现,发动机状态更新

 1 variables2 {3   char BCMStatusPanel[32] = "BCM状态图";4   char EMSCtrl[8] = "发动机";5   6   //本消息由EMS发出,包含引擎转速、加速踏板状态信号7   message 0x334 EMS_EngineRPM;8 9   msTimer EMS_timer;
10 }
11
12 on envVar PEPS_PowerMode
13 {
14   //获取电源模式 + 车速
15   varPowerMode = getValue(PEPS_PowerMode);
16   if(varPowerMode==3)
17   {
18     putValue(EMS_EngStatus, 0);//stop
19     putValue(EMS_EngineSpeedRPM,0);
20     InactiveEMS();
21     lastPowerMode = varPowerMode;
22   }
23   else
24   {
25     if(lastPowerMode==3 && varPowerMode==0)
26     {
27       ;
28     }
29     else
30     {
31       switch(varPowerMode)
32       {
33         case 0:
34           putValue(EMS_EngStatus, 0);//stop
35           putValue(EMS_EngineSpeedRPM,0);
36           break;
37         case 1:
38           putValue(EMS_EngStatus, 0);//stop
39           putValue(EMS_EngineSpeedRPM,0);
40           break;
41         case 2:
42           putValue(EMS_EngStatus, 3);
43           break;
44         case 4:
45           putValue(EMS_EngStatus, 1);//Cranking
46           putValue(EMS_EngineSpeedRPM,0);
47           break;
48         default:
49           break;
50       }
51       ActiveEMS();
52     }
53   }
54 }
55
56 //更新车身仿真器的状态
57 on envVar EMS_EngStatus
58 {
59   int temp;
60   temp = getValue(EMS_EngStatus);
61   EMS_EngineRPM.EMS_EngStatus = temp;
62   if(temp==3)
63   {
64     IsEngineWorking = 1; //发动机工作中
65     setPictureBoxImage(BCMStatusPanel, EMSCtrl, "..\\Panels\\picture\\启动中.bmp");
66   }
67   else if (temp==0)//油车
68   {
69     IsEngineWorking = 0;
70     setPictureBoxImage(BCMStatusPanel, EMSCtrl, "..\\Panels\\picture\\未启动.bmp");
71   }
72   else if(temp==2) //PHEV
73   {
74     if(@GEEA1::varCarType == 2)
75     {
76       IsEngineWorking = 0;
77       setPictureBoxImage(BCMStatusPanel, EMSCtrl, "..\\Panels\\picture\\未启动.bmp");
78     }
79   }
80 }
81
82 //略去 EMS激活,去激活,初始值,报文发送的函数

BCM仿真器实现,四门六盖,锁状态

  1 variables2 {3   char BCMCtrlPanel[32] = "ControlPanel";4   char BCMStatusPanel[32] = "BCM状态图";5   char BCMHoodCtrl[32]= "引擎盖";6   char BCMTrunkCtrl[32]= "后备箱";7   char BCMLFDoorCtrl[32]= "左前门";8   char BCMLRDoorCtrl[32]= "左后门";9   char BCMRFDoorCtrl[32]= "右前门";10   char BCMRRDoorCtrl[32]= "右后门";11   char BCMSunroofCtrl[32]= "天窗";12   char BCMLockCtrl[32]= "锁";13   14   //本消息由BCM发出,包含BCM控制的各类开关以及加热器继电器开关信号15   message 0x1 BCM_StateUpdate;16   //左门窗17   message 0x2 BCM_LDoorWindowState;18   //右门窗19   message 0x3 BCM_RDoorWindowState;20   //本消息由BCM发出,包含前车窗状态及天窗状态信号21   message 0x4 BCM_SunroofState;22   // 发送100ms周期的报文23   msTimer BCM_WndsDoors_timer;24   25 }26 27 on start28 {29   InitBCMValue();30   InitBCMPanels();31   //BCM不受PEPS电源模式影响,所以启动CANoe即可发出BCM报文32   ActiveBCM();33 }34 35 on timer BCM_WndsDoors_timer36 {37   output(BCM_SunroofState);38   output(BCM_StateUpdate);39   output(BCM_LDoorWindowState);40   output(BCM_RDoorWindowState);41   setTimer(BCM_WndsDoors_timer, varCycTime100);42 }43 44 //设置每次启动CANoe时,BCM的初值45 void InitBCMValue()46 {47 }48 49 void InitBCMPanels()50 {51   //打开控制面板 capl function, 此处不指明路径 直接遍历工程目录52   openPanel(BCMCtrlPanel);   53   openPanel(BCMStatusPanel);54 }55 56 //激活BCM往外发送报文57 void ActiveBCM()58 {59   setTimer(BCM_WndsDoors_timer, varCycTime100);60 }61 62 //停发BCM报文63 void InactiveBCM()64 {65   cancelTimer(BCM_WndsDoors_timer);66 }67 68 //预留一开关 停发所有报文69 on envVar PEPS_PowerMode70 {71   varPowerMode = getValue(PEPS_PowerMode);72   if(varPowerMode==3) //CAN-Sleep73   {74     InactiveBCM();75     lastPowerMode = varPowerMode;76   }77   else78   {79     if((varPowerMode==0)&&(lastPowerMode==3))80     {81       ;82     }83     else if((2==varPowerMode) || (1==varPowerMode) || (4==varPowerMode))84     {85       ActiveBCM(); //不是从3跳到0的模式,全激活86     }87     lastPowerMode = varPowerMode;88   }89 }90 //天窗91 on envVar BCM_SunroofAjarStatus92 {93   int temp;94   95   temp = getValue(BCM_SunroofAjarStatus);96   writeDbgLevel(1,"天窗信号=%d",temp);97   BCM_SunroofState.L_Sunroof_Position=temp;98   if(temp==0) //未知99   {
100     setPictureBoxImage(BCMStatusPanel,BCMSunroofCtrl,"..\\Panels\\picture\\天窗未知.bmp");
101   }
102   else if(temp==1) //关闭
103   {
104     setPictureBoxImage(BCMStatusPanel,BCMSunroofCtrl,"..\\Panels\\picture\\天窗关闭.bmp");
105   }
106   else if(temp==2) //开启
107   {
108     setPictureBoxImage(BCMStatusPanel,BCMSunroofCtrl,"..\\Panels\\picture\\天窗未关闭.bmp");
109   }
110 }
111 //驾驶位车窗
112 on envVar BCM_Drv_Wdw_PositionSts
113 {
114   int x,y;
115
116   x = getvalue(BCM_Drv_Wdw_PositionSts);
117   y = getvalue(BCM_FrontLeftDoorAjarStatus);
118   writeDbgLevel(1,"驾驶位车窗=%d",x);
119   BCM_LDoorWindowState.L_Drv_Wdw_PositionSts = x;
120   if((x==1)&&(y==0))
121   {
122    setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前窗开.bmp");
123   }
124   else if((x==1)&&(y==1))
125   {
126    setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前门和窗未关闭.bmp");
127   }
128   else if((x==2)&&(y==0))
129   {
130    setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前门关闭.bmp");
131   }
132   else if((x==2)&&(y==1))
133   {
134    setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前门未关闭.bmp");
135   }
136   else if((x==0)&&(y==0))
137   {
138    setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前窗透气.bmp");
139   }
140    else if((x==0)&&(y==1))
141   {
142    setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前门未关闭窗透气.bmp");
143   }
144 }
145 //左后窗
146 on envVar BCM_RLD_Wdw_PositionSts
147 {
148   int x, y;
149   x = getValue(BCM_RLD_Wdw_PositionSts);
150   y = getValue(BCM_RearLeftDoorAjarStatus);
151   writeDbgLevel(1,"左后车窗=%d",x);
152   BCM_LDoorWindowState.L_RLD_Wdw_PositionSts = x;
153   if((y==0) && (x==1))
154   {
155    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后窗开.bmp");
156   }
157   else if((y==1) && (x==1))
158   {
159    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后门和窗未关闭.bmp");
160   }
161    else if((y==0)&&(x==2))
162   {
163    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后门关闭.bmp");
164   }
165    else if((y==1)&&(x==2))
166   {
167    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后门未关闭.bmp");
168   }
169   else if((y==0)&&(x==0))
170   {
171    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后窗透气.bmp");
172   }
173   else if((y==1)&&(x==0))
174   {
175    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后门未关闭窗透气.bmp");
176   }
177 }
178 //左前门
179 on envVar BCM_FrontLeftDoorAjarStatus
180 {
181   int x, y, z;
182   x = getvalue(BCM_FrontLeftDoorAjarStatus);
183   y = getvalue(BCM_Drv_Wdw_PositionSts);
184   z = getValue(BCM_DoorLockStatusDrv);
185   BCM_LDoorWindowState.BCM_FrontLeftDoorAjarStatus = x;
186   if((x==1) && (z==1) && (varPowerMode==0))
187   { //防盗入侵报警,熄火OFF+锁车+开左前门触发,10s后恢复armed
188      putValue(BCM_ATWS_St,4);  //0x0: Armed0x1: Prearmed0x2: Disarmed0x3: Remind0x4: Alarm0x5: Partially Armed0x6: Not used0x7: Not used
189      BCM_StateUpdate.BCM_ATWS_St=getvalue(BCM_ATWS_St);
190      //setTimer(BCM_ATWS_timer, varCycTime10);
191   }
192   if((y==1)&&(x==0))
193   {
194     setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前窗开.bmp");
195   }
196   if((y==1)&&(x==1))
197   {
198     setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前门和窗未关闭.bmp");
199   }
200   if((y==2)&&(x==0))
201   {
202     setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前门关闭.bmp");
203   }
204   if((y==2)&&(x==1))
205   {
206     setPictureBoxImage(BCMStatusPanel, BCMLFDoorCtrl, "..\\Panels\\picture\\左前门未关闭.bmp");
207   }
208 }
209 //左后门
210 on envVar BCM_RearLeftDoorAjarStatus
211 {
212   int x,y;
213   x = getvalue(BCM_RearLeftDoorAjarStatus);
214   y = getvalue(BCM_RLD_Wdw_PositionSts);
215   BCM_LDoorWindowState.BCM_RearLeftDoorAjarStatus=x;
216   if((x==0)&&(y==1))
217   {
218    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后窗开.bmp");
219   }
220   else if((x==1)&&(y==1))
221   {
222    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后门和窗未关闭.bmp");
223   }
224    else if((x==0)&&(y==2))
225   {
226    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后门关闭.bmp");
227   }
228    else if((x==1)&&(y==2))
229   {
230    setPictureBoxImage(BCMStatusPanel, BCMLRDoorCtrl, "..\\Panels\\picture\\左后门未关闭.bmp");
231   }
232
233 }
234 //驾驶侧锁
235 on envVar BCM_DoorLockStatusDrv
236 {
237   int temp;
238   temp=getValue(BCM_DoorLockStatusDrv);
239   writeDbgLevel(1,"门锁信号=%d",temp);
240   BCM_LDoorWindowState.BCM_DoorLockStatusDrv=temp;
241   if(temp==0)
242   {
243     setPictureBoxImage(BCMStatusPanel,BCMLockCtrl,"..\\Panels\\picture\\锁开.bmp");
244   }
245   else
246   {
247     setPictureBoxImage(BCMStatusPanel,BCMLockCtrl,"..\\Panels\\picture\\锁闭.bmp");
248   }
249 }
250 //左后门锁
251 on envVar BCM_DoorLockStatusRL
252 {
253   BCM_LDoorWindowState.BCM_DoorLockStatusRL=getValue(BCM_DoorLockStatusRL);
254 }
255 //右前窗
256 on envVar BCM_Pas_Wdw_PositionSts
257 {
258   int x,y;
259   x = getvalue(BCM_Pas_Wdw_PositionSts);
260   y = getvalue(BCM_FrontRightDoorAjarStatus);
261   writeDbgLevel(1,"副驾车窗=%d",x);
262   BCM_RDoorWindowState.L_Pas_Wdw_PositionSts=x;
263   if((y==0)&&(x==1))
264   {
265    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前窗开.bmp");
266   }
267   else if((y==1)&&(x==1))
268   {
269    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前门和窗未关闭.bmp");
270   }
271   else if((y==0)&&(x==2))
272   {
273    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前门关闭.bmp");
274   }
275   else if((y==1)&&(x==2))
276   {
277    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前门未关闭.bmp");
278   }
279    else if((y==0)&&(x==0))
280   {
281    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前窗透气.bmp");
282   }
283    else if((y==1)&&(x==0))
284   {
285    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前门未关闭窗透气.bmp");
286   }
287 }
288 //右后窗
289 on envVar BCM_RRD_Wdw_PositionSts
290 {
291   int x,y;
292   x = getvalue(BCM_RRD_Wdw_PositionSts);
293   y = getvalue(BCM_RearRightDoorAjarStatus);
294
295   writeDbgLevel(1,"右后车窗=%d",x);
296   BCM_RDoorWindowState.L_RRD_Wdw_PositionSts=x;
297   if((y==0)&&(x==1))
298   {
299    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后窗开.bmp");
300   }
301   if((y==1)&&(x==1))
302   {
303    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后门和窗未关闭.bmp");
304   }
305   if((y==0)&&(x==2))
306   {
307    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后门关闭.bmp");
308   }
309   if((y==1)&&(x==2))
310   {
311    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后门未关闭.bmp");
312   }
313   if((y==0)&&(x==0))
314   {
315    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后窗透气.bmp");
316   }
317   if((y==1)&&(x==0))
318   {
319    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后门未关闭窗透气.bmp");
320   }
321 }
322 //副驾门锁
323 on envVar BCM_DoorLockStatusPassenger
324 {
325   BCM_RDoorWindowState.BCM_DoorLockStatusPass=getValue(BCM_DoorLockStatusPassenger);
326 }
327 //右后门锁
328 on envVar BCM_DoorLockStatusRR
329 {
330   BCM_RDoorWindowState.BCM_DoorLockStatusRR=getValue(BCM_DoorLockStatusRR);
331 }
332 //右前门
333 on envVar BCM_FrontRightDoorAjarStatus
334 {
335   int x,y;
336   x = getvalue(BCM_Pas_Wdw_PositionSts);;
337   y = getvalue(BCM_FrontRightDoorAjarStatus);
338   BCM_RDoorWindowState.BCM_FrontRightDoorAjarStatus=y;
339   if((y==0)&&(x==1))
340   {
341    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前窗开.bmp");
342   }
343   else if((y==1)&&(x==1))
344   {
345    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前门和窗未关闭.bmp");
346   }
347   else if((y==0)&&(x==2))
348   {
349    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前门关闭.bmp");
350   }
351   else if((y==1)&&(x==2))
352   {
353    setPictureBoxImage(BCMStatusPanel, BCMRFDoorCtrl, "..\\Panels\\picture\\右前门未关闭.bmp");
354   }
355 }
356 //右后门
357 on envVar BCM_RearRightDoorAjarStatus
358 {
359   int x, y;
360   y = getvalue(BCM_RearRightDoorAjarStatus);
361   x = getvalue(BCM_RRD_Wdw_PositionSts);
362   BCM_RDoorWindowState.BCM_RearRightDoorAjarStatus=y;
363  if((y==0)&&(x==1))
364   {
365    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后窗开.bmp");
366   }
367  if((y==1)&&(x==1))
368   {
369    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后门和窗未关闭.bmp");
370   }
371   if((y==0)&&(x==2))
372   {
373    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后门关闭.bmp");
374   }
375   if((y==1)&&(x==2))
376   {
377    setPictureBoxImage(BCMStatusPanel, BCMRRDoorCtrl, "..\\Panels\\picture\\右后门未关闭.bmp");
378   }
379 }
380
381 //一键关门
382 on envVar CloseDoors
383 {
384   int temp;
385   temp = getValue(CloseDoors);
386   if(temp==0) //关闭
387   {
388     putValue(BCM_FrontLeftDoorAjarStatus,0);
389     putValue(BCM_FrontRightDoorAjarStatus,0);
390     putValue(BCM_RearLeftDoorAjarStatus,0);
391     putValue(BCM_RearRightDoorAjarStatus,0);
392
393   }
394   else //开启
395   {
396     putValue(BCM_FrontLeftDoorAjarStatus,1);
397     putValue(BCM_FrontRightDoorAjarStatus,1);
398     putValue(BCM_RearLeftDoorAjarStatus,1);
399     putValue(BCM_RearRightDoorAjarStatus,1);
400   }
401 }
402 //一键关窗
403 on envVar CloseWnds
404 {
405   int temp;
406   temp = getValue(CloseWnds);
407   //writeDbgLevel(1,"一键关窗=%d",temp);
408   if(temp==0) //关闭
409   {
410     putValue(BCM_Drv_Wdw_PositionSts,2);
411     putValue(BCM_Pas_Wdw_PositionSts,2);
412     putValue(BCM_RLD_Wdw_PositionSts,2);
413     putValue(BCM_RRD_Wdw_PositionSts,2);
414
415     //天窗
416     putValue(BCM_SunroofAjarStatus, 1);
417     //开度值=0
418     putValue(BCM_Val_Wdw_Opened,0);
419   }
420   else //全开
421   {
422     putValue(BCM_Drv_Wdw_PositionSts,1);
423     putValue(BCM_Pas_Wdw_PositionSts,1);
424     putValue(BCM_RLD_Wdw_PositionSts,1);
425     putValue(BCM_RRD_Wdw_PositionSts,1);
426
427     //可屏蔽天窗
428     putValue(BCM_SunroofAjarStatus, 2);
429     //开度值=100
430     putValue(BCM_Val_Wdw_Opened,100);
431   }
432 }
433 //一键锁止
434 on envVar LockDoors
435 {
436   int temp;
437   temp = getValue(LockDoors);
438   if(1==temp)//锁
439   {
440     putValue(BCM_DoorLockStatusDrv,1);
441     putValue(BCM_DoorLockStatusRL,1);
442     putValue(BCM_DoorLockStatusPassenger,1);
443     putValue(BCM_DoorLockStatusRR,1);
444     setPictureBoxImage(BCMStatusPanel,BCMLockCtrl,"..\\Panels\\picture\\锁闭.bmp");
445   }
446   else //未锁
447   {
448     putValue(BCM_DoorLockStatusDrv,0);
449     putValue(BCM_DoorLockStatusRL,0);
450     putValue(BCM_DoorLockStatusPassenger,0);
451     putValue(BCM_DoorLockStatusRR,0);
452     setPictureBoxImage(BCMStatusPanel,BCMLockCtrl,"..\\Panels\\picture\\锁开.bmp");
453   }
454 }
455
456 //防盗报警状态
457 on envVar BCM_ATWS_St
458 {
459   BCM_StateUpdate.BCM_ATWS_St = getValue(BCM_ATWS_St);
460 }
461
462 //BCM信号提示后盖箱/后车门开启/关闭
463 on envVar BCM_TrunkAjarStatus
464 {
465   int temp;
466
467   temp = getValue(BCM_TrunkAjarStatus);
468   BCM_StateUpdate.BCM_TrunkAjarStatus=temp;
469   if(temp==0) //关闭
470   {
471     setPictureBoxImage(BCMStatusPanel,BCMTrunkCtrl,"..\\Panels\\picture\\后备箱关闭.bmp");
472   }
473   else{ //开启
474     setPictureBoxImage(BCMStatusPanel,BCMTrunkCtrl,"..\\Panels\\picture\\后备箱未关闭.bmp");
475   }
476 }
477
478 //BCM信号提示引擎盖开启/关闭
479 on envVar BCM_HoodAjarStatus
480 {
481   int temp;
482
483   temp = getValue(BCM_HoodAjarStatus);
484   BCM_StateUpdate.BCM_HoodAjarStatus=temp;
485   if(temp==0)
486   {
487     setPictureBoxImage(BCMStatusPanel, BCMHoodCtrl, "..\\Panels\\picture\\引擎盖关闭.bmp");
488   }
489   else if(temp==1)
490   {
491     setPictureBoxImage(BCMStatusPanel, BCMHoodCtrl, "..\\Panels\\picture\\引擎盖未关闭.bmp");
492   }
493   else
494   {
495     writeDbgLevel(1, "预留值,无定义");
496   }
497 }
498
499 on envVar  BCM_Val_Wdw_Opened
500 {
501   int temp;
502   temp = getValue(BCM_Val_Wdw_Opened);
503   writeDbgLevel(1, "窗户开度值=%d", temp);
504   BCM_RDoorWindowState.L_Pas_Val_Wdw_Opened=temp;
505   BCM_RDoorWindowState.L_RRD_Val_Wdw_Opened=temp;
506   BCM_LDoorWindowState.L_Drv_Val_Wdw_Opened=temp;
507   BCM_LDoorWindowState.L_RLD_Val_Wdw_Opened=temp;
508 }

6、PEPS仿真+T业务主逻辑实现

T业务,处理远程业务时,需根据产品的DBC中定义的报文去解读信号,判断业务逻辑。(示例代码中处理业务逻辑的信号解析规则属于随便举例,实际应用时根据DBC定义进行解读)

  1 variables2 {3   char log[128];4   float tFactor = 100000.0;  //时间精度值5   //本消息由PEPS发出, 鉴权6   message 0x5 PEPS_TELChallengeCode;7   //本消息由GW发送,包括PEPS的电源模式及报警信号等8   message 0x6 GW_Info;9   //由TBOX反馈的应答码10   message 0x7 TBOX_ResponseCode;11   12   msTimer GW_PEPS_Timer;13   //远程控制的PEPS响应定时器14   msTimer GW_PEPS_TimerRespSuccess;15   //接收到报文的定时器16   msTimer GW_PEPS_TimerRespReceived;17   //PEPS启动认证码的定时器,只发三帧18   msTimer GW_PEPS_TimerSendChallengeCode;19   //远程启动定时器20   timer RespRmtEngineWorkingTimer;21   22   //PM 净化定时器23   timer RmtAirCleanTimer;24   //加热定时器25   timer RmtDrvHeatTimer;26   timer RmtPasHeatTimer;27   //空调允许时间28   timer RmtACOnTimer;29   //30   timer UpdateStatusTimer;31   32   //以下内容属于PEPS加密算法的内容33   const dword SC32 = 0x00112233;34   const qword CC64 = 0x94254547464A5B7DLL; //后最LL35   //SK128 无法获取; RN32 每次鉴权随机生成;36   dword RN32;37   //设别远程启动的类型;在发生鉴权行为的时候会使用到38   //1=启动;2=熄火;3=使能;4=禁止;0 预留39   int rmtReqTpye=0;40   //是否已认真过41   int IsAuthed = 0;42   43   44   //远程控制请求45   byte rmtCtrlReq;46   // 远程查询PM2.547   byte rmtReqPM;48   //远程查询49   byte rmtReqQ;50   //远程启动51   byte rmtStartReq;52   byte rmtStopReq;53   //远程加热座椅54   byte rmtHeatDrvSeat;55   byte rmtHeatPasSeat;56   57   //远程开关空调58   byte rmtACReq; //byte(3) 温度值+空调的启停状态59   byte acReq;60   byte acTemp;61   62   //远程空气净化63   byte rmtAirCleanerReq;64   65   //发动机运行时长 分级66   byte rmtEngWorkTimeLvl = 0;67   int rmtEngWorkTime = 0;  //远程发动机启动时长, 单位s68   //延时69   byte rmtEngWorkDelayTimeLvl = 0;70   //远程运行时间71   int rmtWorkTime = 0; //包含启动空调,加热,绿净的时长72   int tempWorkTime; //临时变量 存放rmtworkTime73   //远程禁允发动机74   byte rmtForbidEngReq;75   byte rmtPermitEngReq;76   77   //记忆PEPS应答报文的发送次数78   int pepsRespCnt=0;79   //记忆PEPS认证报文的发送次数80   int pepsAuthCnt=0;81   //82   int pepsRecvCnt=0;83 }84 85 on start86 {87   InitLogging();88   InitPEPSValue();89   ActivePEPS();90   91 }92 93 //关闭CANoe时 停止记录LOG94 on stopMeasurement95 {96   writeDestroy(mTrace);97 }98 99 //标记当前电源模式, 3=休眠开关, KL15电源通断可使用VT板卡实现,否则手动操作实现为半自动化方案
100 on envVar PEPS_PowerMode
101 {
102   varPowerMode = getValue(PEPS_PowerMode);
103   //刷新报文值
104   GW_Info.PEPS_PowerMode = varPowerMode;
105   if(varPowerMode==3)
106   {
107     InactivePEPS();
108     lastPowerMode = varPowerMode;
109   }
110   else
111   {
112     if((varPowerMode==0)&&(lastPowerMode==3))
113     {
114       ;
115     }
116     else if((2==varPowerMode) || (1==varPowerMode) || (4==varPowerMode))
117     {
118       ActivePEPS(); //不是从3跳到0的模式,全激活
119     }
120     lastPowerMode = varPowerMode;
121   }
122 }
123
124
125 //标记PEPS应答的错误码
126 on envVar PEPS_FailReason2TBOX
127 {
128   int temp;
129   temp = getValue(PEPS_FailReason2TBOX);
130   writeDbgLevel(1,"PEPS_FailReason2TBOX=0x%x",temp);
131   GW_Info.PEPS_FailReason2TBOX = temp;
132 }
133 //标记PEPS应答的成功与否
134 on envVar PEPS_StatusResponse2TBOX
135 {
136   GW_Info.PEPS_StatusResponse2TBOX = getValue(PEPS_StatusResponse2TBOX);
137 }
138 //标记发动机的启动模式
139 on envVar PEPS_RemoteControlSt
140 {
141   GW_Info.PEPS_RemoteControlSt=getValue(PEPS_RemoteControlSt);
142 }
143
144 /***********************************************************
145 * description  : TBOX响应T业务的请求的报文
146 * parameter    : None
147 * creation date: 2018/10/17
148 * author       : xxx
149 * revision date:
150 * revision log :
151 * modifier     :
152 ***********************************************************/
153 on message TBOX_RmtCtrlInfo  //此消息由DBC中定义的远程控制报文可获取, 具体的报文解析,字节信号位等由DBC定义
154 {
155   rmtReqQ = (this.byte(1) & 0x03);
156   //远程控制 + 查询类
157   rmtCtrlReq = this.TBOX_DoorsLock;
158   rmtReqPM = this.TBOX_PM25;
159
160   //远程发动机延时等级
161   rmtEngWorkDelayTimeLvl = this.TBOX_EngineDelayTime;
162   rmtStartReq = this.TBOX_EngineStartReq;
163   rmtStopReq = this.TBOX_EngineStopReq;
164   rmtACReq = this.byte(3);
165   rmtAirCleanerReq = this.TBOX_AirCleanerReq;
166   rmtForbidEngReq = this.TBOX_EngineForbidReq;
167   rmtPermitEngReq = this.TBOX_EnginePermitReq;
168   //PEPSRespReceived(); //只要一接到接收指令 立即回复处理中
169   //远程控制
170   RespRmtCtrlCmd(rmtCtrlReq);
171   if(0 != rmtEngWorkDelayTimeLvl) //如果不等于0, 有控制请求
172   {
173     PEPSRespReceived();
174     switch(rmtEngWorkDelayTimeLvl)
175     {
176       case 0x1://1min
177         rmtWorkTime = 60;
178         break;
179       case 0x2://3min
180         rmtWorkTime = 180;
181         break;
182       case 0x3://5min
183         rmtWorkTime = 300;
184         break;
185       case 0x4://10min
186         rmtWorkTime = 600;
187         break;
188       default:
189         break;
190     }
191     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,发动机运行时间延长%d", timeNow()/tFactor, rmtWorkTime);
192     writeLineEx(mTrace, INFO, log);
193     PEPSRespSuccess();
194   }
195   //远程查询
196   if(1 == rmtReqPM)
197   {
198     PEPSRespReceived();
199     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,PM2.5查询", timeNow()/tFactor);
200     writeLineEx(mTrace, INFO, log);
201     putValue(AC_PM25Sts, 2);//complate
202     PEPSRespSuccess();
203   }
204   if(3 == rmtReqQ)
205   {
206     PEPSRespReceived();
207     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,查询天窗车窗", timeNow()/tFactor);
208     writeLineEx(mTrace, INFO, log);
209     PEPSRespSuccess();
210   }
211   //远程启动
212   if(1 == rmtStartReq)
213   {
214     PEPSRespReceived();
215     rmtReqTpye = 1;
216     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,启动发动机", timeNow()/tFactor);
217     writeLineEx(mTrace, INFO, log);
218     rmtEngWorkTimeLvl = this.TBOX_EngineStartTime;
219     switch(rmtEngWorkTimeLvl)
220     {
221       case 0x1://1min
222         rmtEngWorkTime = 60;
223         break;
224       case 0x2://3min
225         rmtEngWorkTime = 180;
226         break;
227       case 0x3://5min
228         rmtEngWorkTime = 300;
229         break;
230       case 0x4://10min
231         rmtEngWorkTime = 600;
232         break;
233       default:
234         break;
235     }
236     snprintf(log, elcount(log),"%f <- TBOX, 启动发动机时长%d", timeNow()/tFactor, rmtEngWorkTime);
237     writeLineEx(mTrace, INFO, log);
238     PEPSReqAuth();
239   }
240
241   //远程停止
242   if(rmtStopReq==1)
243   {
244     rmtReqTpye = 2;
245     PEPSRespReceived();
246
247     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,停止发动机", timeNow()/tFactor);
248     writeLineEx(mTrace, INFO, log);
249
250     PEPSRespSuccess();
251     RespRmtStop();
252   }
253    //远程禁止发动机
254   if(1 == rmtForbidEngReq)
255   {
256     rmtReqTpye = 4;
257     PEPSRespReceived();
258     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,禁止启动", timeNow()/tFactor);
259     writeLineEx(mTrace, INFO, log);
260
261     PEPSReqAuth();
262   }
263   //远程使能发动机
264   if(1 == rmtPermitEngReq)
265   {
266     rmtReqTpye = 3;
267     PEPSRespReceived();
268     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,允许启动", timeNow()/tFactor);
269     writeLineEx(mTrace, INFO, log);
270
271     PEPSReqAuth();
272   }
273   //PM 净化
274   if(2==rmtAirCleanerReq) //2=ON , 1=OFF, 0=No Req
275   {
276     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,空气净化开启", timeNow()/tFactor);
277     writeLineEx(mTrace, INFO, log);
278
279     PEPSRespReceived();
280     PEPSRespSuccess();
281     RespRmtOpenAirClean();  //区分
282   }
283   else if(1==rmtAirCleanerReq)
284   {
285     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令,空气净化关闭", timeNow()/tFactor);
286     writeLineEx(mTrace, INFO, log);
287
288     PEPSRespReceived();
289     PEPSRespSuccess();
290     RespRmtCloseAirClean();
291   }
292
293   //远程空调
294   if(0x1F != rmtACReq) //2=ON , 1=OFF, 0=No Req
295   {
296     PEPSRespReceived();
297     acReq = ((rmtACReq >> 6) & 0x3);
298     acTemp = (rmtACReq & 0x1F);
299     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令, 操作空调req=%d, temp=%d", timeNow()/tFactor,acReq,acTemp);
300     writeLineEx(mTrace, INFO, log);
301
302     PEPSRespSuccess();
303     if(2==acReq)
304     {
305       RespRmtOpenAC();  //open
306     }
307     else if(1==acReq)
308     {
309       RespRmtCloseAC();  //close
310     }
311   }
312   if(this.byte(4)!=0xE7)
313   {
314     rmtHeatDrvSeat = this.TBOX_DrvHeatReq;
315     rmtHeatPasSeat = this.TBOX_PassHeatReq;
316
317     snprintf(log, elcount(log),"%f <- TBOX, 接收到指令, 座椅加热Drv=%d,Pas=%d", timeNow()/tFactor,rmtHeatDrvSeat, rmtHeatPasSeat);
318     writeLineEx(mTrace, INFO, log);
319
320     PEPSRespReceived();
321     PEPSRespSuccess();
322     //主驾
323     switch(rmtHeatDrvSeat)
324     {
325       case 0x0:
326         RespRmtCloseDrvHeat();
327         break;
328       case 0x1:
329         RespRmtOpenDrvHeat(rmtHeatDrvSeat);
330         break;
331       case 0x2:
332         RespRmtOpenDrvHeat(rmtHeatDrvSeat);
333         break;
334       default:
335         break;
336     }
337
338     //副驾
339     switch(rmtHeatPasSeat)
340     {
341       case 0x0:
342         RespRmtClosePasHeat();
343         break;
344       case 0x1:
345         RespRmtOpenPasHeat(rmtHeatPasSeat);
346         break;
347       case 0x2:
348         RespRmtOpenPasHeat(rmtHeatPasSeat);
349         break;
350       default:
351         break;
352     }
353   }
354 }
355
356 //TBOX响应PEPS挑战码,发出的认证码
357 on message TBOX_ResponseCode
358 {
359   snprintf(log, elcount(log),"%f <- TBOX, response peps auth request", timeNow()/tFactor);
360   writeLineEx(mTrace, INFO, log);
361   //PEPS回复控制成功通过
362   PEPSRespSuccess();
363   if(rmtReqTpye == 1){
364     RespRmtStart();
365     //设置发动机的运行模式与运行时长,启动定时器
366     snprintf(log, elcount(log),"%f <- TBOX, engine work time=%d", timeNow()/tFactor, rmtEngWorkTime);
367     writeLineEx(mTrace, INFO, log);
368     setTimer(RespRmtEngineWorkingTimer, rmtEngWorkTime);
369   }
370   else if(rmtReqTpye == 2) //实测关闭发动机不需要鉴权
371   {
372     RespRmtStop();
373   }
374   else if(3 == rmtReqTpye) //使能
375   {
376     RespRmtPermit();
377   }
378   else if(4 == rmtReqTpye) //禁止
379   {
380     RespRmtForbidden();
381   }
382 }
383
384 //远程启动发动机运行时长定时器
385 on timer RespRmtEngineWorkingTimer
386 {
387   //发动机置位远程启动模式
388   putValue(PEPS_RemoteControlSt,0);
389   //电源置为ON
390   putValue(PEPS_PowerMode, 0);
391   //发动机置位running
392   putValue(EMS_EngStatus,0);
393 }
394
395 //空调开启一段时间后 更新温度传感器信号
396 on timer UpdateStatusTimer
397 {
398   ; //未实现
399 }
400
401 //空调运行时长定时器
402 on timer RmtACOnTimer
403 {
404   putValue(AC_OnState, 0);
405 }
406
407 //空气净化运行时长定时器
408 on timer RmtAirCleanTimer
409 {
410   putValue(AC_AirCleanState, 0);
411   putValue(AC_OnState,0);
412 }
413
414 //主驾加热运行时长定时器
415 on timer RmtDrvHeatTimer
416 {
417   putValue(HVSM_DrvHeatSts, 0);
418 }
419
420 //副驾加热运行时长定时器
421 on timer RmtPasHeatTimer
422 {
423   putValue(HVSM_PassHeatSts,0);
424 }
425
426 //响应远程加热主驾座椅
427 void RespRmtOpenDrvHeat(int level)
428 {
429   putValue(HVSM_DrvHeatSts,level);
430   if((1==IsEngineWorking) && (rmtWorkTime!=0))
431   {
432     snprintf(log, elcount(log),"%f -> HVSM, 先启动发动机,再开启座椅加热,延长发动机运行时长%d", timeNow()/tFactor, rmtWorkTime);
433     writeLineEx(mTrace, INFO, log);
434     tempWorkTime = rmtWorkTime;
435     cancelTimer(RespRmtEngineWorkingTimer); //取消原定时器
436     setTimer(RespRmtEngineWorkingTimer, tempWorkTime); //重置发动机定时器
437     setTimer(RmtDrvHeatTimer, tempWorkTime);
438     rmtWorkTime=0;
439   }
440   else
441   {
442     snprintf(log, elcount(log),"%f -> HVSM, 直接座椅加热,发动机运行时长%d", timeNow()/tFactor, rmtEngWorkTime);
443     writeLineEx(mTrace, INFO, log);
444     setTimer(RmtDrvHeatTimer, rmtEngWorkTime);
445   }
446 }
447
448 //响应远程加热副驾座椅
449 void RespRmtOpenPasHeat(int level)
450 {
451   putValue(HVSM_PassHeatSts,level);
452   if((1==IsEngineWorking) && (rmtWorkTime!=0))
453   {
454     snprintf(log, elcount(log),"%f -> HVSM, 先启动发动机,再加热座椅,延长发动机运行时长%d", timeNow()/tFactor, rmtWorkTime);
455     writeLineEx(mTrace, INFO, log);
456     tempWorkTime = rmtWorkTime;
457     cancelTimer(RespRmtEngineWorkingTimer); //取消原定时器
458     setTimer(RespRmtEngineWorkingTimer, tempWorkTime); //重置发动机定时器
459     setTimer(RmtPasHeatTimer, tempWorkTime);
460     rmtWorkTime=0; //用完后归零
461   }
462   else
463   {
464     snprintf(log, elcount(log),"%f -> HVSM, 直接加热座椅,发动机运行时长%d", timeNow()/tFactor, rmtEngWorkTime);
465     writeLineEx(mTrace, INFO, log);
466     setTimer(RmtPasHeatTimer, rmtEngWorkTime);
467   }
468 }
469
470 //响应关闭座椅加热
471 void RespRmtCloseDrvHeat()
472 {
473   cancelTimer(RmtDrvHeatTimer);
474   putValue(HVSM_DrvHeatSts, 0);
475 }
476
477 //响应关闭座椅加热
478 void RespRmtClosePasHeat()
479 {
480   cancelTimer(RmtPasHeatTimer);
481   putValue(HVSM_PassHeatSts, 0);
482 }
483
484 //响应开启空调
485 void RespRmtOpenAC()
486 {
487   putValue(AC_OnState, 1);
488   if((1==IsEngineWorking) && (rmtWorkTime!=0))
489   {
490     //先启动发动机 后启动空调
491     snprintf(log, elcount(log),"%f -> AC, 先启动发动机,再开启空调,延长发动机运行时长%d", timeNow()/tFactor, rmtWorkTime);
492     writeLineEx(mTrace, INFO, log);
493     tempWorkTime = rmtWorkTime;
494     cancelTimer(RespRmtEngineWorkingTimer); //取消原定时器
495     setTimer(RespRmtEngineWorkingTimer, tempWorkTime); //重置发动机定时器
496     setTimer(RmtACOnTimer, tempWorkTime);
497     rmtWorkTime=0; //用完后归零
498   }
499   else
500   {
501     //直接启动空调
502     snprintf(log, elcount(log),"%f -> AC, 直接启动空调,发动机运行时长%d", timeNow()/tFactor, rmtEngWorkTime);
503     writeLineEx(mTrace, INFO, log);
504     setTimer(RmtACOnTimer, rmtEngWorkTime);
505   }
506 }
507
508 //响应关闭空调
509 void RespRmtCloseAC()
510 {
511   cancelTimer(RmtACOnTimer);
512   putValue(AC_OnState, 0);
513 }
514
515 //响应关闭空气净化
516 void RespRmtCloseAirClean()
517 {
518   cancelTimer(RmtAirCleanTimer);
519   putValue(AC_AirCleanState, 0);
520   putValue(AC_OnState, 0);
521
522 }
523
524 //响应开启PM净化
525 void RespRmtOpenAirClean()
526 {
527   putValue(AC_OnState, 1);
528   putValue(AC_AirCleanState, 1);
529   if((1==IsEngineWorking)  && (rmtWorkTime!=0))
530   {
531     //先启动发动机 后启动PM净化
532     snprintf(log, elcount(log),"%f -> AC, 先启动发动机 再开空气净化,延长发动机运行时间%d", timeNow()/tFactor, rmtWorkTime);
533     writeLineEx(mTrace, INFO, log);
534     tempWorkTime = rmtWorkTime;
535     cancelTimer(RespRmtEngineWorkingTimer); //取消原定时器
536     setTimer(RespRmtEngineWorkingTimer, rmtWorkTime); //重置发动机定时器
537     setTimer(RmtAirCleanTimer, rmtWorkTime); //置位空气净化定时器
538     rmtWorkTime = 0;
539   }
540   else
541   {
542     //直接启动PM净化
543     snprintf(log, elcount(log),"%f -> AC, 直接开启空气净化,发动机运行时间%d", timeNow()/tFactor, rmtEngWorkTime);
544     writeLineEx(mTrace, INFO, log);
545     setTimer(RmtAirCleanTimer, rmtEngWorkTime); //置位空气净化定时器
546   }
547
548 }
549
550 //响应远程控制指令
551 void RespRmtCtrlCmd(int cmd)
552 {
553   //判断远程控制类逻辑
554   switch(cmd){
555     case 0x0://No command
556       break;
557     case 0x1://All door lock
558       snprintf(log, elcount(log),"%f <- TBOX, 接收上锁指令", timeNow()/tFactor);
559       writeLineEx(mTrace, INFO, log);
560       SetDoorsLocked();
561       PEPSRespSuccess();
562       break;
563     case 0x2://Blink lamp  闪灯
564       break;  //APP未实现单独指令
565     case 0x3://All door unlock
566       snprintf(log, elcount(log),"%f <- TBOX, 接收解锁指令", timeNow()/tFactor);
567       writeLineEx(mTrace, INFO, log);
568       SetDoorsUnlocked();
569       PEPSRespSuccess();
570       break;
571     case 0x4://Whistle    鸣笛
572       break;  //APP未实现单独指令
573     case 0x5://Global closing-window up
574       snprintf(log, elcount(log),"%f <- TBOX, 接收关窗指令", timeNow()/tFactor);
575       writeLineEx(mTrace, INFO, log);
576       SetWndsClosed();
577       PEPSRespSuccess();
578       break;
579     case 0x6://Closing window
580       break; //APP未实现单独指令
581     case 0x7: //Closing sunroof
582       break;    //APP未实现单独指令
583     case 0x8://Global opening-window down
584       snprintf(log, elcount(log),"%f <- TBOX, 接收开窗指令", timeNow()/tFactor);
585       writeLineEx(mTrace, INFO, log);
586       SetWndsOpened();
587       PEPSRespSuccess();
588       break;
589     case 0x9://Vehicle search
590       snprintf(log, elcount(log),"%f <- TBOX, 接收寻车指令", timeNow()/tFactor);
591       writeLineEx(mTrace, INFO, log);
592       PEPSRespSuccess();
593       break;
594     case 0xA://Trunk unlock
595       snprintf(log, elcount(log),"%f <- TBOX, 接收开启后备箱指令", timeNow()/tFactor);
596       writeLineEx(mTrace, INFO, log);
597       SetTrunkOpened();
598       PEPSRespSuccess();
599       break;
600     case 0xB://Window ventilate
601       snprintf(log, elcount(log),"%f <- TBOX, 接收透气指令", timeNow()/tFactor);
602       writeLineEx(mTrace, INFO, log);
603       SetWndsVentilate();
604       PEPSRespSuccess();
605       break;
606     case 0xC://Opening sunroof
607       break;   //APP未实现单独指令
608     default://others are reserved
609       break;   //预留指令
610   }
611 }
612
613 //远程禁止启动发动机
614 void RespRmtForbidden()
615 {
616   GW_Info.PEPS_EngineforbidSt=1;
617 }
618
619 //远程允许启动发动机
620 void RespRmtPermit()
621 {
622   GW_Info.PEPS_EngineforbidSt=0;
623 }
624
625
626 //远程停止发动机
627 void RespRmtStop()
628 {
629   cancelTimer(RespRmtEngineWorkingTimer);
630
631   putValue(PEPS_RemoteControlSt,0);
632   putValue(EMS_EngStatus, 0);
633   putValue(PEPS_PowerMode, 0);
634   //停止发动机后  所有控制器开的状态都归零
635   putValue(AC_AirCleanState, 0);
636   putValue(AC_OnState,0);
637   putValue(HVSM_DrvHeatSts, 0);
638   putValue(HVSM_PassHeatSts, 0);
639 }
640
641 //响应远程启动
642 void RespRmtStart()
643 {
644   IsAuthed =0;
645   putValue(EMS_EngStatus, 0);
646
647   //发动机置位远程启动模式
648   putValue(PEPS_RemoteControlSt,1);
649   //发动机置位running
650   putValue(EMS_EngStatus, 3);
651   //电源置为ON
652   putValue(PEPS_PowerMode, 2);
653   IsEngineWorking = 1; //标记发动机已经工作中, Delay时间不会发出
654   snprintf(log, elcount(log),"%f <- EMS PEPS, Engine running, Power on", timeNow()/tFactor);
655   writeLineEx(mTrace, INFO, log);
656   //TestWaitForTimeout(3000);//延时函数在纯CAPL程序中不能使用
657 }
658
659 //初始化电源模式
660 void InitPEPSValue()
661 {
662   putValue(PEPS_PowerMode, 0);
663   putValue(PEPS_StatusResponse2TBOX,0);
664   putValue(PEPS_FailReason2TBOX,0);
665   putValue(PEPS_RemoteControlSt,0);
666   GW_Info.PEPS_PowerModeValidity = 2;
667   GW_Info.PEPS_EngineforbidSt=0;  //发动机允许远程使能状态
668 }
669
670 void ActivePEPS()
671 {
672   setTImer(GW_PEPS_Timer, varCycTime100);
673 }
674
675 void InactivePEPS()
676 {
677   cancelTimer(GW_PEPS_Timer);
678 }
679
680 //每次鉴权生成随机认证码
681 void GenerateRN32()
682 {
683   RN32 = random(0xFFFFFFFF);
684 }
685
686 //窗户透气响应
687 void SetWndsVentilate()
688 {
689   //窗户开
690   putValue(BCM_Drv_Wdw_PositionSts,0);
691   putValue(BCM_RLD_Wdw_PositionSts,0);
692   putValue(BCM_Pas_Wdw_PositionSts,0);
693   putValue(BCM_RRD_Wdw_PositionSts,0);
694   putValue(BCM_Val_Wdw_Opened, 20); //开度值20%
695 }
696
697 //响应远程关闭车窗指令
698 void SetWndsClosed()
699 {
700 //  putValue(CloseWnds,0);
701   putValue(BCM_Drv_Wdw_PositionSts,2);
702   putValue(BCM_RLD_Wdw_PositionSts,2);
703   putValue(BCM_Pas_Wdw_PositionSts,2);
704   putValue(BCM_RRD_Wdw_PositionSts,2);
705   putValue(BCM_Val_Wdw_Opened, 0);
706 }
707
708 //响应远程上锁指令
709 void SetDoorsLocked()
710 {
711   putValue(LockDoors,1);
712 }
713
714 //响应远程解锁指令
715 void SetDoorsUnlocked()
716 {
717   putValue(LockDoors,0);
718 }
719
720 //响应远程开窗指令
721 void SetWndsOpened()
722 {
723 //  putValue(CloseWnds,1);//开启
724   putValue(BCM_Drv_Wdw_PositionSts,1);
725   putValue(BCM_RLD_Wdw_PositionSts,1);
726   putValue(BCM_Pas_Wdw_PositionSts,1);
727   putValue(BCM_RRD_Wdw_PositionSts,1);
728   putValue(BCM_Val_Wdw_Opened, 100);
729 }
730
731 //响应远程打开后备箱
732 void SetTrunkOpened()
733 {
734   putValue(BCM_TrunkAjarStatus, 1); //开启后备箱
735 }
736
737 //PEPS回复控制成功报文
738 void PEPSRespSuccess()
739 {
740   setTimer(GW_PEPS_TimerRespSuccess, varCycTime100);
741 }
742
743 void PEPSRespReceived()
744 {
745 //  setTimer(GW_PEPS_TimerRespReceived, varCycTime20);
746 }
747
748 //PEPS发起认证请求
749 void PEPSReqAuth()
750 {
751   //算法不实现!
752   //若实际环境中接入了PEPS设备,则需实车抓取报文使用固定一组报文访问
753   //安全隐患,PEPS入侵(可能设计:每次随机的挑战码,携带当前时间,设置计数器和校验位验证有效性,限定时间内的重复报文无效)
754   if(rmtReqTpye ==1)
755   {
756     GenerateChallengeCode4Start();
757   }
758   else if(rmtReqTpye ==2)
759   {
760     GenerateChallengeCode4Stop();
761   }
762
763   setTimer(GW_PEPS_TimerSendChallengeCode, varCycTime20);
764   IsAuthed = 1; //已经发起过鉴权
765 }
766
767 void GenerateChallengeCode4Stop()
768 {
769   //关闭发动机鉴权
770 }
771 //生成PEPS挑战码,启动发动机鉴权
772 void GenerateChallengeCode4Start()
773 {
774   if(pepsAuthCnt==0)
775   {
776     PEPS_TELChallengeCode.PEPS_TELchallengeCode_Byte0 = random(0xff);
777     PEPS_TELChallengeCode.PEPS_TELchallengeCode_Byte1 = random(0xff);
778     PEPS_TELChallengeCode.PEPS_TELchallengeCode_Byte2 = random(0xff);
779     PEPS_TELChallengeCode.PEPS_TELchallengeCode_Byte3 = random(0xff);
780     PEPS_TELChallengeCode.PEPS_TELchallengeCode_Byte4 = random(0xff);
781     PEPS_TELChallengeCode.PEPS_TELchallengeCode_Byte5 = random(0xff);
782     PEPS_TELChallengeCode.PEPS_TELchallengeCode_Byte6 = random(0xff);
783     PEPS_TELChallengeCode.PEPS_TELchallengeCode_Byte7 = random(0xff);
784   }
798 }
799
800 //TBOX预约充电请求(电动车)/
801 on message TBOX_ReservationChgSet
802 {
803   //线束不支持双路CAN 暂且无法实现
804 }
805
806 //TBOX被唤醒的原因指示
807 on message NWM_TBOX_Information
808 {
809   int reasons;
810   reasons = this.TBOX_Wakeup_reasons;
811   switch(reasons){
812     case 0x2:
813       writeLineEx(mTrace, 1, "NM PDU Received");
814       break;
815     case 0x5:
816       writeLineEx(mTrace, 1, "KL15 On");
817       break;
818     case 0x06:
819       writeLineEx(mTrace, 1, "Telematics service");
820       break;
821     default:
822       break;
823   }
824 }
825
826 //PEPS周期报文发送
827 on timer GW_PEPS_Timer
828 {
829   output(GW_Info);
830   setTimer(GW_PEPS_Timer, varCycTime100);
831 }
832
833 //响应远程请求,PEPS反馈Received
834 on timer GW_PEPS_TimerRespReceived
835 {
836   pepsRecvCnt+=1;
837   if(pepsRecvCnt<2)
838   {
839     snprintf(log, elcount(log),"%f -> PEPS, response 'in progress'", timeNow()/tFactor);
840     writeLineEx(mTrace, INFO, log);
841     putValue(PEPS_FailReason2TBOX,  0);
842     putValue(PEPS_StatusResponse2TBOX, 1);
843     setTimer(GW_PEPS_TimerRespReceived, varCycTime20); //200ms一帧
844   }
845   else
846   {
847     cancelTimer(GW_PEPS_TimerRespReceived);
848     putValue(PEPS_FailReason2TBOX, 0);
849     putValue(PEPS_StatusResponse2TBOX, 0);
850     pepsRecvCnt = 0;
851   }
852 }
853
854 //响应远程请求,PEPS反馈Success
855 on timer GW_PEPS_TimerRespSuccess
856 {
857   pepsRespCnt+=1;
858   if(pepsRespCnt<2)
859   {
860     snprintf(log, elcount(log),"%f -> PEPS, response 'success'", timeNow()/tFactor);
861     writeLineEx(mTrace, INFO, log);
862     putValue(PEPS_FailReason2TBOX,  0);
863     putValue(PEPS_StatusResponse2TBOX, 2);
864     setTimer(GW_PEPS_TimerRespSuccess, varCycTime100);
865   }
866   else
867   {
868     cancelTimer(GW_PEPS_TimerRespSuccess);
869     putValue(PEPS_FailReason2TBOX, 0);
870     putValue(PEPS_StatusResponse2TBOX, 0);
871     pepsRespCnt = 0;
872   }
873 }
874
875 //响应远程启动请求, PEPS发出挑战码
876 on timer GW_PEPS_TimerSendChallengeCode
877 {
878
879   pepsAuthCnt+=1;
880   if(pepsAuthCnt<2)
881   {
882     snprintf(log, elcount(log),"%f -> PEPS, send challenge code", timeNow()/tFactor);
883     writeLineEx(mTrace, INFO, log);
884
885     output(PEPS_TELChallengeCode);
886     setTimer(GW_PEPS_TimerSendChallengeCode, varCycTime20);//递归 发三帧,20ms一帧
887   }
888   else
889   {
890     cancelTimer(GW_PEPS_TimerSendChallengeCode);
891     pepsAuthCnt = 0;
892   }
893 }

7、效果展示

整个车辆网功能中涉及到整车中其它ECU相关的业务,也可参照以上实现逻辑去进行仿真。此处不一一举例。

我在台架中接入真实仪表验证我的仿真逻辑(节点支持热增减,没有ECU则使用仿真节点,有真实ECU则屏蔽)。

启动仿真程序后,操作控制器,验证车身仿真器的实现,可以检验出仿真代码实现的正确性

--------------------------以上T业务自动化仿真测试台架全内容完结

最新文章

  1. 【Java】5大排序算法总结(插入排序+希尔排序+选择排序+堆排序+冒泡排序)
  2. python使用matplotlib可视化堆积的折线图、使用stackplot函数可视化堆积的折线图、不同数据在垂直方向堆叠
  3. server多笔记录拼接字符串 sql_Java拼接“1亿行字符串”你会遇到什么问题?
  4. 有进度条圆周率Π计算
  5. 探索测试 | 新奇深层测试策略之案例剖析(一)
  6. 浅谈C语言static关键字 静态变量 函数
  7. URL编码 URLEncoder 示例
  8. java中src_java中garadle工程没有src问题
  9. 换了路由器电脑都连不上网了_高校连上网自由都实现不了?三大运营商:这锅我不背...
  10. MICROSOFT REPORTVIEWER(微软报表)项目中的应用
  11. 云计算业务优势扩大,阿里云业务持续高速增长
  12. 世界上最伟大最邪恶的软件发明
  13. MySQL关系一对多一对一多对多
  14. 通信协议晦涩难懂搞不定?看完这些动图恍然大悟
  15. FPGA 控制 nand flash读写
  16. 蓝桥杯国赛2017瓷砖样式
  17. Win 10-jdk 8 下载和安装步骤
  18. html在360浏览器如何修改字体大小,360浏览器网页中字体大小如何修改
  19. 青龙面板搭配诺兰nvjdc详细教程
  20. UpdateData()函数的用法

热门文章

  1. 大学一年级计算机组成语结构试题,一年级下册期末复习习题
  2. tiny4412 linux-4.2 移植(十一)LCD驱动移植
  3. Tomcat内存溢出的三种情况及解决办法分析
  4. python身份证验证程序_python 身份证验证
  5. 产品读书《创新者的窘境》
  6. Himall商城普通帮助类(四)
  7. 只用一招!Python实现微信防撤回!
  8. Java读取数据库中的数据
  9. js打开新窗口与页面跳转
  10. 使用JS实现表单验证