选择用于监控消息的通道
最后修改:
该函数允许应用程序选择通道以监控可用消息(包括指示消息)。应用程序可以指定物理通道与逻辑通道的任意组合、具有可用消息的最少通道数量以及超时时间。
在发生以下任一情况之前,该函数不会返回控制权:
Timeout 到期ChannelList 中具有可用消息的通道数量达到或超过 ChannelThresholdlong PassThruSelect(
SCHANNELSET *ChannelSetPtr,
unsigned long SelectType,
unsigned long Timeout
)
PassThruSelect 允许应用程序检查并等待多个通道上消息的可用性,而无需持续调用
PassThruReadMsgs。这可以最大限度地减少应用程序与设备之间的数据交换,从而提升性能。
PassThruSelect 不返回消息本身,仅返回哪些通道具有可用消息的信息。要获取消息,需调用 PassThruReadMsgs。
输入参数。指向由应用程序分配的 SCHANNELSET 结构的指针。
输入参数。指定通道选择的用途。唯一允许的值为:
| 值 | 说明 |
|---|---|
READABLE_TYPE |
监控通道是否存在可用消息(接收的消息或指示消息) |
输入参数。等待所需数量消息可用的最短时间(以毫秒为单位)。
ChannelThreshold = 0)typedef struct {
unsigned long ChannelCount; // 列表中的通道数量
unsigned long ChannelThreshold; // 具有消息的最少通道数量
unsigned long *ChannelList; // 指向通道 ID 数组的指针
} SCHANNELSET;
| 字段 | 输入/输出 | 说明 |
|---|---|---|
ChannelCount |
输入/输出 | 调用时:ChannelList 中的通道数量。返回时: ChannelList 中剩余的通道数量(具有可用消息的通道)。 |
ChannelThreshold |
输入 | 必须至少具有一条可用消息的最少通道数量。值为 0 时,函数立即返回(等同于 Timeout = 0)。必须 ≤ ChannelCount。 |
ChannelList |
输入/输出 | 调用时:指向待监控通道(物理和/或逻辑)ID 数组的指针。 返回时:原始列表的子集——仅包含具有可用消息的通道(顺序不保证)。 |
| 代码 | 说明 |
|---|---|
| STATUS_NOERROR | 函数执行成功。ChannelList 包含具有可用消息的通道。 |
| ERR_CONCURRENT_API_CALL | 在上一次调用完成之前调用了 J2534 API 函数 |
| ERR_DEVICE_NOT_OPEN | 未成功调用 PassThruOpen() |
| ERR_NULL_PARAMETER | ChannelSetPtr 或 ChannelList 为 NULL |
| ERR_INVALID_CHANNEL_ID | ChannelList 中的某个通道 ID 无效。SCHANNELSET 结构不会被修改。 |
| ERR_DEVICE_NOT_CONNECTED | 与 pass-thru 设备的通信错误。设备已断开连接。 |
| ERR_NOT_SUPPORTED | DLL 不支持该函数 |
| ERR_SELECT_TYPE_NOT_SUPPORTED | SelectType 的值无效或未知 |
| ERR_EXCEEDED_LIMIT | ChannelThreshold 的值大于 ChannelCount |
| ERR_BUFFER_EMPTY | 指定的任何通道上均无可用消息 |
| ERR_TIMEOUT | 超时已到期,且具有消息的通道数量少于 ChannelThreshold。仅在 Timeout 非零且至少存在一条消息时适用。 |
| ERR_FAILED | 未定义的错误。使用 PassThruGetLastError() 获取说明。 |
#include "j2534_dll.hpp"
// 从 PassThruConnect/PassThruLogicalConnect 获取的通道 ID
unsigned long canChannelID = ...;
unsigned long isoChannelID = ...;
// 用于监控的通道数组
unsigned long channels[2] = { canChannelID, isoChannelID };
// PassThruSelect 所需的结构
SCHANNELSET channelSet;
channelSet.ChannelCount = 2;
channelSet.ChannelThreshold = 1; // 至少等待 1 个有消息的通道
channelSet.ChannelList = channels;
// 等待消息,最长 1000 毫秒
long ret = PassThruSelect(&channelSet, READABLE_TYPE, 1000);
if (ret == STATUS_NOERROR) {
printf("有消息的通道数量:%lu\n", channelSet.ChannelCount);
// 从有数据的通道读取消息
for (unsigned long i = 0; i < channelSet.ChannelCount; i++) {
unsigned long channelID = channelSet.ChannelList[i];
printf("通道 %lu 有消息\n", channelID);
// 读取消息
PASSTHRU_MSG msg[10];
unsigned long numMsgs = 10;
ret = PassThruReadMsgs(channelID, msg, &numMsgs, 0);
// ...处理消息...
}
} else if (ret == ERR_BUFFER_EMPTY) {
printf("无可用消息\n");
} else if (ret == ERR_TIMEOUT) {
printf("超时,但有 %lu 个通道存在消息\n", channelSet.ChannelCount);
} else {
char error[256];
PassThruGetLastError(error);
printf("错误:%s\n", error);
}
from ctypes import *
j2534 = cdll.LoadLibrary("libj2534_v05_00.dylib")
# SCHANNELSET 结构
class SCHANNELSET(Structure):
_fields_ = [
("ChannelCount", c_ulong),
("ChannelThreshold", c_ulong),
("ChannelList", POINTER(c_ulong))
]
# 通道 ID
can_channel_id = c_ulong(...) # 来自 PassThruConnect
iso_channel_id = c_ulong(...) # 来自 PassThruLogicalConnect
# 通道数组
channels = (c_ulong * 2)(can_channel_id.value, iso_channel_id.value)
# PassThruSelect 所需的结构
channel_set = SCHANNELSET()
channel_set.ChannelCount = 2
channel_set.ChannelThreshold = 1
channel_set.ChannelList = channels
READABLE_TYPE = 0x01
# 等待消息,最长 1000 毫秒
ret = j2534.PassThruSelect(byref(channel_set), READABLE_TYPE, 1000)
if ret == 0: # STATUS_NOERROR
print(f"有消息的通道数量:{channel_set.ChannelCount}")
for i in range(channel_set.ChannelCount):
print(f"通道 {channel_set.ChannelList[i]} 有消息")
elif ret == 0x10: # ERR_BUFFER_EMPTY
print("无可用消息")
elif ret == 0x09: # ERR_TIMEOUT
print(f"超时,有消息的通道数量:{channel_set.ChannelCount}")
else:
error = create_string_buffer(256)
j2534.PassThruGetLastError(error)
print(f"错误:{error.value.decode()}")
PassThruReadMsgs() - 从通道读取消息PassThruConnect() - 建立物理连接PassThruLogicalConnect() - 建立逻辑通道