重要提示
服务应当支持物理寻址方式请求,部分服务也支持功能寻址方式请求。在功能寻址请求的方式下有些时候不需要回复否定响应:
- ServiceNotSupport
- ServiceNotSupportInActiveSession
- SubFunctionNotSupport
- SubFunctionNotSupportInActiveSession
- requstOutOfRange
服务器一般响应行为
以下响应行为是从接受到请求开始验证的,服务器响应分为三个部分:
**强制数据**: 评估每个请求消息
**可选数据**: 根据需要选择性评估请求消息
**制造商/供应商规定**: 根据制造商/供应商的规定评估具体信息
可选验证 :检查当前服务器如果处于忙碌状态,回复NRC 0x21,否则,继续向下验证;
制造商指定验证 :根据制造商规定验证对应的请求信息是否满足,并根据需设置相应的NRC,否则,继续向下验证;
强制验证 :请求的服务是否支持,(判断当前的服务器是否设置了对此SID的支持,不是UDS是否支持),如果不支持,回复NRC 0x11,否则继续向下验证;
强制验证 :验证当前的session是否支持请求的服务,如果不支持,回复NRC 0x7F,否则继续向下验证;
可选验证 :根据服务情况选择是否需要验证SA,如果SA验证未通过,回复NRC 0x33,否则继续向下验证;
供应商指定验证 :根据供应商规定验证对应的请求信息是否满足,并根据需设置相应的NRC,否则,继续向下验证;
一般性响应行为到此,下面有两个分支:
- 包含子功能的服务(并不包括SID 0x31)
- 其他服务
子功能占据一个Byte,包含bit0-bit7,其中bit7是正响应抑制位,当bit7=1时,正响应会被抑制,但是如果中间服务器发送了0x78的否定响应,也需要发送最终响应。即0x78需要发送的最终响应效果>正响应抑制位的抑制效果
包含子功能的请求响应行为
强制验证 :检查请求的服务是否满足最小长度,不满足回复NRC 0x13,否则继续向下验证;(至少两个字节,包含SID和SF参数)
强制验证 :检查此服务是否支持请求的子功能,不支持回复NRC 0x12,否则继续向下验证;(检查是否设置了此SF)
强制验证 :检查当前会话是否支持请求的子功能,不支持回复NRC 0x7E,否则继续向下验证;
可选验证 :检查当前的SA是否支持请求的子功能,不支持回复NRC 0x33,否则继续向下验证;
可选验证 :检查子功能的顺序是否正确(eg:27服务先请求seed再比较key),不正确回复NRC 0x24,否则继续向下验证;
制造商/供应商指定 :根据规定验证对应的请求信息是否满足,并根据需设置相应的NRC,否则,继续向下验证;
物理寻址请求
带子功能的物理寻址请求响应行为。
a:物理寻址,不抑制正响应,服务和子功能都支持,参数至少有一个可用时,服务器回复肯定响应;
b:物理寻址,不抑制正响应,服务和子功能都支持,参数至少有一个可用时,如果请求数据参数错误,服务器回复否定响应;
c:物理寻址,不抑制正响应,服务和子功能都支持,没有可用的数据参数,服务器回复NRC 0x31的否定响应;
d:物理寻址,不抑制正响应,服务不支持,服务器回复NRC 0x11或0x7F的否定响应;
e:物理寻址,不抑制正响应,服务支持,子功能不支持,服务器回复NRC 0x12或0x7E的否定响应;
f:物理寻址,抑制正响应,服务和子功能都支持,参数至少有一个可用时,抑制正响应;
g:物理寻址,抑制正响应,服务和子功能都支持,参数至少有一个可用时,如果请求数据参数错误,服务器回复否定响应;
h:物理寻址,抑制正响应,服务和子功能都支持,没有可用的数据参数,服务器回复NRC 0x31的否定响应;
i:物理寻址,抑制正响应,服务不支持,服务器回复NRC 0x11或0x7F的否定响应;
j:物理寻址,不抑制正响应,服务支持,子功能不支持,服务器回复NRC 0x12或0x7E的否定响应;
此处,i,j表中NRC各少了一个,个人认为是表中记录错了。原文档的解析中有一句描述是g-j与b-e是相同的,因为物理寻址的否定响应不关注正响应抑制位的设置情况。
**还有一点,如果服务器在处理某一条请求的时候使用了NRC 0x78作为回复,那么一定要在后面回复最终的肯定响应或者NRC不是0x78的最终响应。这意味着在f的情况下,如果使用了0x 78去延长响应的执行时间,最后也要给出一个最终响应。**
功能寻址请求
带子功能的物理寻址请求响应行为。
a:功能寻址,不抑制正响应,服务和子功能都支持,参数至少一个可用,服务器回复肯定响应;
b:功能寻址,不抑制正响应,服务和子功能都支持,参数至少有一个可用时,如果请求数据参数错误,服务器回复否定响应;
c:功能寻址,不抑制正响应,服务和子功能都支持,没有可用参数,功能寻址抑制NRC 0x31(ROOR)的否定响应;
d:功能寻址,不抑制正响应,服务不支持,服务器抑制NRC 0x11或0x7F的否定响应;
e:功能寻址,不抑制正响应,服务支持,子功能不支持,服务器抑制NRC 0x12或0x7E的否定响应;
f:功能寻址,抑制正响应,服务和子功能都支持,参数至少一个可用,服务器抑制肯定响应;
g:功能寻址,抑制正响应,服务和子功能都支持,参数至少一个可用,但是由于一些错误,服务器发送否定响应
h:功能寻址,抑制正响应,服务器和子功能都支持,参数不可用,功能寻址抑制NRC 0x31(ROOR)的否定响应;
i:功能寻址,抑制正响应,服务不支持,服务器抑制NRC 0x11或0x7F的否定响应;
j:功能寻址,不抑制正响应,服务支持,子功能不支持,服务器抑制NRC 0x12或0x7E的否定响应。
没有子功能参数的服务响应行为
对于没有子功能参数的的请求消息,没有通用的服务器响应行为可用。
物理寻址客户端请求
此子项中指定的服务器响应行为在每个服务的服务描述中引用,该服务不支持子函数参数,但支持从客户端收到的物理寻址请求消息中的数据参数。
a:物理寻址,服务和参数都支持,服务器回复肯定响应;
b:物理寻址,服务支持,至少有一个可用参数,服务器回复肯定响应;
c:物理寻址,服务支持,至少有一个参数可用,但是由于一些错误,服务器发送否定响应;
d:物理寻址,服务支持,没有可用参数,服务器回复NRC 0x31的否定响应;
e:物理寻址,服务不支持,服务器回复NRC 0x11或0x7F的否定响应。
功能寻址客户端请求
此子项中指定的服务器响应行为在每个服务的服务描述中引用,该服务不支持子函数参数,但支持从客户端收到的功能性地址请求消息中的数据参数。
a:功能寻址,服务和参数都支持,服务器发送正响应;
b:功能寻址,服务支持,至少一个参数可用,服务器回复肯定响应;
c:功能寻址,服务支持,至少一个参数可用,但是由于一些错误,服务器发送否定响应;
d:功能寻址,服务支持,没有参数可用,服务器抑制NRC 0x31的否定响应
e:功能寻址,服务不支持,服务器抑制NRC 0x11或0x7F的否定响应
伪代码示例
SWITCH (A_PDU.A_Data.A_PCI.SI)
{
CASE Service_with_sub-function: /* 如果服务子功能支持*/
IF (message_length >= 2) THEN /* 检查最小长度SI+SF */
SWITCH (A_PDU.A_Data.A_Data.Parameter1 & 0x7F) /*检查是否抑制正响应*/
{
CASE sub-function_00: /* 如果子功能00支持*/
IF (message_length == expected_sub-function_message_length) THEN /* 如果消息长度正确,组装响应*/
responseCode = positiveResponse; /* 正响应消息,NRC设置为无效的否定相应码*/
ELSE
responseCode = IMLOIF; /* 否则,长度不正确,回复NRC 0x13*/
ENDIF
BREAK;
CASE sub-function_01: /* 如果子功能01支持 */ /* 组装响应*/
responseCode = positiveResponse; /* 正响应消息,NRC设置为无效的否定相应码*/
: /*等等等等,判断其他的子功能参数*/
CASE sub-function_127: /* 如果子功能127支持 */ /* 组装响应*/
responseCode = positiveResponse; /* 正响应消息,NRC设置为无效的否定相应码*/
BREAK;
DEFAULT:
responseCode = SFNS; /* 其他情况,说明不支持的子功能,设置NRC 0x12 */
}
ELSE
responseCode = IMLOIF; /* 如果最小长度不满足,设置NRC 0x13 */
ENDIF
suppressPosRspMsgIndicationBit = (A_PDU.A_Data.Parameter1 & 0x80); /*获取正响应抑制位信息, 0x00或者0x80 */
IF ( (suppressPosRspMsgIndicationBit) && (responseCode == positiveResponse) && (“not yet a NRC 0x78 response sent”)) THEN
/* 如果抑制正响应,而且要求的是回复正响应,并且没有发送过0x78 */
suppressResponse = TRUE; /* 抑制正响应标记为TRUE */
ELSE
suppressResponse = FALSE; /* 否则,抑制正响应标记为Falise*/
ENDIF
BREAK;
CASE Service_without_sub-function: /*如果服务不包含子功能 */
suppressResponse = FALSE; /* 抑制响应的标志初始化为False */
IF (message_length == expected_message_length) THEN
IF (A_PDU.A_Data.Parameter1 == supported) THEN /* 如果消息长度支持,服务支持*/
responseCode = positiveResponse; /* 正响应消息,NRC设置为无效的否定相应码*/
ELSE
responseCode = ROOR; /* 如果参数不支持,设置NRC 0x31 */
ENDIF
ELSE
responseCode = IMLOIF; /* 如果长度不满足,设置NRC 0x13 */
ENDIF
BREAK;
DEFAULT:
responseCode = SNS; /* 如果服务不支持,设置NRC 0x11 */
}
IF (A_PDU.TA_type == functional && ((responseCode == SNS) ¦¦ (responseCode == SFNS) ¦¦ (responseCode == SNSIAS) ¦¦
(responseCode == SFNSIAS) ¦¦ (responseCode == ROOR)) &&(“not yet a NRC 0x78 response sent”)) THEN
/* 如果是功能寻址,否定响应是以上几个,且没有发送过0X78 */
············
ELSE
IF (suppressResponse == TRUE) THEN /* 否则,如果抑制正响应*/
·········
ELSE /* 发送响应 */
······
ENDIF
······
ENDIF