我在CAPL中创建了一个非常简单的状态机,告诉我信号何时变高以及在关闭之前它保持打开的时间。 现在我有大约70个信号,我需要知道信号何时开始以及在进入OFF之前它保持多长时间。 我已经实现的代码在这里。
我的问题:有没有办法模板化这个状态机的功能,所以我不必在代码中的任何地方实现它。
on message x639
{
message x639 mil_obj;
mil_obj = this;
switch(mil_state)
{
case MIL_OFF:
{
if(mil_obj.iHwEcm_MILInput_flg == 1)
{
mil_start_time = (timeNow()/100000);
mil_state = MIL_ON;
}
else
{
mil_state = MIL_OFF;
}
break;
}
case MIL_ON:
{
if(mil_obj.iHwEcm_MILInput_flg == 0)
{
mil_stop_time = (timeNow()/100000);
mil_retval = writeCreate("MIL_STATUS");
writeLineEx(mil_retval,1," MIL turned ON at %ld seconds for a duration of %ld seconds ", mil_start_time, mil_stop_time - mil_start_time);
mil_stop_time =0;
mil_start_time =0;
mil_state = MIL_OFF;
}
else
{
mil_state = MIL_ON;
}
break;
}
default:
break;
}
output(mil_obj);
}
答案 0 :(得分:1)
有可能避免为每个信号复制粘贴代码。
您可以使用数组为您感兴趣的每个信号存储状态和start_time。访问这些数组有点棘手,因为您没有像std :: map中那样的构造
state["Signal1"] = STATE_ON;
因此,创建一个存储信号名称,状态和start_time的结构(在您的示例中不需要保存stop_time,因为在计算并输出它之后它不会被使用)。像:
struct signal_state {
char sig_name[100];
int last_value;
int start_time;
};
然后制作大量这些状态(因此每个信号都适合)
每当您想要访问信号状态时,您必须遍历数组并strcmp()
所有带有您要访问的信号的值都能获得正确的数组索引。对于非常大的阵列来说,这可能需要花费很多时间,但是对于你的70个信号,它几乎可以立即计算出来。
以下代码应该非常接近您的实际需求:
/*@!Encoding:1252*/
includes
{
}
variables
{
const max_sig_name_len = 100;
const max_num_states = 100;
struct signal_state {
char sig_name[max_sig_name_len];
int last_value;
int start_time;
};
int num_states = 0;
struct signal_state states[max_num_states];
}
on start {
register_signal("CAN1::net1::Message1::Signal1");
register_signal("CAN1::net1::Message2::Signal2");
}
on signal Signal1 {
handle_signal(this.name, this.raw);
output(this);
}
on signal Signal2 {
handle_signal(this.name, this.raw);
output(this);
}
void register_signal(char foo[]) {
strncpy(states[num_states].sig_name, foo, max_sig_name_len);
num_states++;
}
void handle_signal(char sig_name[], int sig_value) {
int i;
for (i = 0; i < num_states; i++) {
if (strncmp(sig_name, states[i].sig_name, max_sig_name_len) == 0)
break;
//writeLineEx(0,1, "%s != %s", this.name, states[i].sig_name);
}
// i now contains the index of the state that represents the current signal
if (i < num_states) {
if ( sig_value == 0 && states[i].last_value > 0) {
int stop_time;
stop_time = timeNow()/100000;
writeLineEx(0,1, "signal %s turned ON at %ld seconds for a duration of %ld seconds.", states[i].sig_name, states[i].start_time, stop_time - states[i].start_time );
} else if (sig_value > 0 && states[i].last_value == 0) {
states[i].start_time = timeNow()/100000;
}
states[i].last_value = sig_value;
}
}
register_signal()
只是填充数组的便捷方式。
必须在您感兴趣的信号的handle_signal()
处理程序中调用on signal
。