DBLookup 动态读取数据库中的信息
//Transmitter 属性以及数据库属性只能通过 DBLookup 动态读取。
//返回数据库中存储的 DLC
on message *
{
int myAttributeValue;
myAttributeValue = DBLookup(this).MyAttribute;
write(this.Transmitter); // compiler error
write(DBLookup(this).Transmitter); // OK
}
//返回特定消息的当前值
on message EngineData
{
int myDLC;
myDLC = DBLookup(this).DLC;
}
myDLC = EngineData.DLC;
它们可能会有所不同,因为 DLC 可以更改,例如 在 CAPL 程序中。
在数据库中动态搜索消息可能需要一些时间,尤其是对于大型数据库。 因此,如果消息类型已知,最好静态访问属性。
// 检查特定节点的所有消息,表明 DLC 正确。
// 在测量结束变量的表中总结不正确 DLC 的 DLC 信息
{
// system under test
char gNodeUnderTest[30] = "Gateway";
// max DLC, min DLC, counter, channel; key is always the id
int gFrameMaxDLC[long];
int gFrameMinDLC[long];
int gFrameCounter[long];
byte gFrameChannel[long];
}
on message *
{
// 检查来自一个节点的所有帧是否有正确的 dlc 并对其进行计数
// 框架是在数据库中定义的吗?
if (DBLookup(this))
{
// 被测节点的帧是否定义为 Tx-Frame?
// 注意:比较区分大小写
if (strncmp(DBLookup(this).Transmitter, gNodeUnderTest, 30) == 0)
{
// 检查DLC是否正确; 如果没有,请记住最小值
// 或接收帧的最大 DLC
if (this.dlc < DBLookup(this).DLC)
{
gFrameCounter[this.id]++;
gFrameChannel[this.id] = this.can;
if (!gFrameMinDLC.containsKey(this.id) || this.dlc < gFrameMinDLC[this.id])
gFrameMinDLC[this.id] = this.dlc;
}
else if (this.dlc > DBLookup(this).DLC)
{
gFrameCounter[this.id]++;
gFrameChannel[this.id] = this.can;
// 注意:第一次访问映射元素返回 0,它总是较小的
if (this.dlc > gFrameMaxDLC[this.id]) gFrameMaxDLC[this.id] = this.dlc;
}
} // else: another node, not interesting
} // else: event is not defined in the database
output(this); // 仅当节点位于测量设置中时使用
}
on stopMeasurement
{
message * m;
for (long currentId : gFrameCounter)
{
m.id = currentId;
m.can = gFrameChannel[currentId];
write ("Frame %s[%d]:", DBLookup(m).Name, currentId);
write (" Incorrect count: %d", gFrameCounter[currentId]);
write (" DLC as in DB: %d", DBLookup(m).DLC);
if (gFrameMinDLC.containsKey(currentId))
write ("Actual min DLC: %d", gFrameMinDLC[currentId]);
if (gFrameMaxDLC.containsKey(currentId))
write ("Actual max DLC: %d", gFrameMaxDLC[currentId]);
}
}
Access to Node
对于某些应用程序,了解特定节点发送或接收哪些消息非常有用。 可以通过专门的预定义字段访问特定节点的所有消息的 ID,并特别迭代这些字段的内容。
以下字段可用:
Nodename.Tx:包含节点发送的所有消息
Nodename.Rx:包含节点接收到的所有消息
Nodename.ALL:包含节点发送和接收的所有消息
如果多个数据库中包含同名节点,则可以使用数据库名称对其进行限定: DBName::Nodename.Tx。
// 检查节点的所有消息,表明 DLC 正确。
// 在测量结束时在表中汇总消息的 DLC 信息。
// 仅在测量之前或之后使用数据库查找
variables
{
// max DLC, min DLC, counter, channel; key is always the id
int gFrameMaxDLC[long];
int gFrameMinDLC[long];
int gFrameDefaultDLC[long];
dword gFrameCounter[long];
dword gFrameIncorrectCounter[long];
}
on preStart
{
dword i;
message * m;
m.can = 2;
// 使用 DB 中定义的默认 DLC 初始化 DLC 映射
for (i = 0; i < elcount(PowerTrain::Gateway.TX); ++i)
{
m.id = PowerTrain::Gateway.TX[i];
gFrameMaxDLC[m.id] = gFrameMinDLC[m.id] = gFrameDefaultDLC[m.id]
= DBLookup(m).DLC;
}
}
on message *
{
// is the frame one of those transmitted by the node?
if (gFrameDefaultDLC.containsKey(this.id))
{
gFrameCounter[this.id]++;
// check if the DLC is correct; if not, remember the minimum
// or maximum DLC of the received frames
if (this.dlc != gFrameDefaultDLC[this.id])
gFrameIncorrectCounter[this.id]++;
if (this.dlc < gFrameMinDLC[this.id])
gFrameMinDLC[this.id] = this.dlc;
else if (this.dlc > gFrameMaxDLC[this.id])
gFrameMaxDLC[this.id] = this.dlc;
} // else: another node, not interesting
output(this); // 仅当节点位于测量设置中时使用
}
on stopMeasurement
{
message * m;
m.can = 2;
for (long currentId : gFrameDefaultDLC)
{
m.id = currentId;
write ("Frame %s[%d]:", DBLookup(m).Name, currentId);
write (" Received count: %d", gFrameCounter[currentId]);
write (" Incorrect count: %d", gFrameIncorrectCounter[currentId]);
write (" DLC as in DB: %d", DBLookup(m).DLC);
write (" Actual min DLC: %d", gFrameMinDLC[currentId]);
write (" Actual max DLC: %d", gFrameMaxDLC[currentId]);
}
}