Quantex GmbH
您的地区:欧洲

PassThruReadMsgs v4.04 v5.0

读取已接收的消息

最后更新:

说明

该函数从通道队列中读取已接收的消息。适配器每个通道的每个队列最多可接收 100 条消息,并为所有队列提供 64 KB 的可用内存。当队列或全部可用内存被填满时,消息接收将被暂停。

long PassThruReadMsgs(unsigned long ChannelID, PASSTHRU_MSG* pMsg, unsigned long* pNumMsgs, unsigned long Timeout)
重要 对于 ISO 9141、ISO 14230 协议,每接收一个数据包,而在 ISO 15765 中每接收一个分段数据包,都会生成一条指示消息 START_OF_MESSAGE,并带有接收开始的时间戳。其后紧跟带有接收结束时间戳的主消息。

参数

返回的错误码

代码 说明 可能原因及解决方法
STATUS_NOERROR 函数执行成功 -
ERR_CONCURRENT_API_CALL v5.0 API 并发调用
  • 在上一次调用完成之前调用了 SAE J2534 API 函数
  • 解决方法:在发起新调用前,请等待上一次调用完成
ERR_DEVICE_NOT_OPEN v5.0 设备未打开
  • 未成功调用 PassThruOpen
  • 解决方法:使用前请先调用 PassThruOpen
ERR_DEVICE_NOT_CONNECTED 未与适配器建立连接
  • 适配器已关闭或连接丢失
  • 解决方法:请检查适配器供电和网络连接
ERR_INVALID_DEVICE_ID 设备标识符无效
  • DeviceID 不是通过 PassThruOpen 获取的
  • 解决方法:请确认设备已打开
ERR_INVALID_CHANNEL_ID 通道标识符无效
  • ChannelID 不是通过 PassThruConnect 获取的
  • 通道已关闭
  • 解决方法:请确认通道已打开
ERR_NOT_SUPPORTED v5.0 不支持该函数
  • 对于该 ChannelID,设备不支持此 API 函数
  • 解决方法:请检查设备的功能支持情况
ERR_NULL_PARAMETER 未提供缓冲区指针
  • pMsg 或 pNumMsgs 为 NULL
  • 解决方法:请传入有效的指针
ERR_TIMEOUT 等待超时已到
  • 在指定时间内到达的消息数量少于请求的数量
  • 解决方法:这是正常情况,请检查 pNumMsgs 以获取实际接收的数量
ERR_BUFFER_EMPTY 接收队列为空
  • 当 Timeout = 0 时队列中没有消息
  • 解决方法:请稍后重试或使用非零超时时间
ERR_BUFFER_OVERFLOW 接收队列已溢出
  • 由于溢出,部分消息已丢失
  • 解决方法:请更频繁地读取消息或提高轮询频率
ERR_BUFFER_TOO_SMALL v5.0 缓冲区太小
  • PASSTHRU_MSG 结构体中的 DataBuffer 大小不足以容纳完整消息
  • 解决方法:请增大数据缓冲区的大小
ERR_NO_FLOW_CONTROL 未设置 Flow Control 过滤器
  • ISO 15765 需要 Flow Control 过滤器
  • 解决方法:请使用 FLOW_CONTROL_FILTER 类型调用 PassThruStartMsgFilter
ERR_FAILED 内部错误
  • 内存分配错误或协议栈故障
  • 解决方法:请使用 PassThruGetLastError() 获取详细信息

示例

C/C++ 示例

#include "j2534_dll.hpp"

unsigned long ChannelID; // 从 PassThruConnect 获取的 ID
PASSTHRU_MSG Msgs[10];   // 消息缓冲区
unsigned long NumMsgs = 10; // 请求最多 10 条消息
unsigned long Timeout = 1000; // 超时时间 1000 毫秒

long ret = PassThruReadMsgs(ChannelID, &Msgs[0], &NumMsgs, Timeout);
if (ret == STATUS_NOERROR || ret == ERR_TIMEOUT)
{
    // 处理接收到的消息(共 NumMsgs 条)
    for (unsigned long i = 0; i < NumMsgs; i++) {
        if (Msgs[i].RxStatus & START_OF_MESSAGE) {
            // 消息开始指示符
            continue;
        }
        // 处理数据 Msgs[i].Data、Msgs[i].DataSize
    }
}
else
{
    char error[256];
    PassThruGetLastError(error);
    printf("Error: %s\n", error);
}

Kotlin (Android) 示例

// channelID 此前从 ptConnect 获取
val numMsgsToRead = 10
val timeout = 1000 // 毫秒

val result = j2534.ptReadMsgs(channelID, numMsgsToRead, timeout)
if (result.status == STATUS_NOERROR || result.status == ERR_TIMEOUT) {
    // 成功读取 result.msgs.size 条消息
    for (msg in result.msgs) {
        if (msg.rxStatus and START_OF_MESSAGE != 0) {
            continue // 跳过开始指示符
        }
        Log.i("J2534", "已接收: ${msg.data.toHexString()}")
    }
} else {
    Log.e("J2534", "读取错误: ${result.status}")
}

Python (ctypes) 示例

from ctypes import *
import platform

# 加载库
if platform.system() == "Windows":
    j2534 = windll.LoadLibrary("j2534sd_v04_04_x64.dll")
elif platform.system() == "Darwin":
    j2534 = cdll.LoadLibrary("libj2534_v04_04.dylib")
else:
    j2534 = cdll.LoadLibrary("libj2534_v04_04.so")

# PASSTHRU_MSG 结构体
class PASSTHRU_MSG(Structure):
    _fields_ = [
        ("ProtocolID", c_ulong),
        ("RxStatus", c_ulong),
        ("TxFlags", c_ulong),
        ("Timestamp", c_ulong),
        ("DataSize", c_ulong),
        ("ExtraDataIndex", c_ulong),
        ("Data", c_ubyte * 4128)
    ]

# channel_id 此前从 PassThruConnect 获取
msgs = (PASSTHRU_MSG * 10)()
num_msgs = c_ulong(10)
timeout = c_ulong(1000)

ret = j2534.PassThruReadMsgs(channel_id, byref(msgs[0]), byref(num_msgs), timeout)

if ret == 0 or ret == 0x09:  # STATUS_NOERROR or ERR_TIMEOUT
    print(f"已接收 {num_msgs.value} 条消息")
    for i in range(num_msgs.value):
        if msgs[i].RxStatus & 0x02:  # START_OF_MESSAGE
            continue
        data = bytes(msgs[i].Data[:msgs[i].DataSize])
        print(f"数据: {data.hex()}")
else:
    error = create_string_buffer(256)
    j2534.PassThruGetLastError(error)
    print(f"错误: {error.value.decode()}")

C# (P/Invoke) 示例

using System;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
public struct PASSTHRU_MSG
{
    public uint ProtocolID;
    public uint RxStatus;
    public uint TxFlags;
    public uint Timestamp;
    public uint DataSize;
    public uint ExtraDataIndex;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4128)]
    public byte[] Data;
}

class J2534
{
    [DllImport("j2534sd_v04_04_x64.dll", CallingConvention = CallingConvention.StdCall)]
    public static extern int PassThruReadMsgs(
        uint ChannelID,
        [In, Out] PASSTHRU_MSG[] pMsg,
        ref uint pNumMsgs,
        uint Timeout);

    [DllImport("j2534sd_v04_04_x64.dll", CallingConvention = CallingConvention.StdCall)]
    public static extern int PassThruGetLastError(
        [MarshalAs(UnmanagedType.LPStr)] System.Text.StringBuilder pErrorDescription);
}

// 用法:
// channelId 此前从 PassThruConnect 获取
PASSTHRU_MSG[] msgs = new PASSTHRU_MSG[10];
for (int i = 0; i < msgs.Length; i++)
    msgs[i].Data = new byte[4128];

uint numMsgs = 10;
uint timeout = 1000;

int ret = J2534.PassThruReadMsgs(channelId, msgs, ref numMsgs, timeout);

if (ret == 0 || ret == 0x09) // STATUS_NOERROR or ERR_TIMEOUT
{
    Console.WriteLine($"已接收 {numMsgs} 条消息");
    for (uint i = 0; i < numMsgs; i++)
    {
        if ((msgs[i].RxStatus & 0x02) != 0) // START_OF_MESSAGE
            continue;
        byte[] data = new byte[msgs[i].DataSize];
        Array.Copy(msgs[i].Data, data, msgs[i].DataSize);
        Console.WriteLine($"数据: {BitConverter.ToString(data)}");
    }
}
else
{
    var error = new System.Text.StringBuilder(256);
    J2534.PassThruGetLastError(error);
    Console.WriteLine($"错误: {error}");
}