Выбор каналов для мониторинга сообщений
Последнее изменение:
Функция позволяет приложению выбрать каналы для мониторинга доступных сообщений (включая индикации). Приложение может указать любую комбинацию физических и логических каналов связи, минимальное количество каналов с доступными сообщениями и таймаут.
Функция не возвращает управление до тех пор, пока не произойдёт одно из следующего:
TimeoutChannelList с доступными сообщениями достигнет или превысит 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 | Один из ID каналов в ChannelList недействителен. Структура 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"
// ID каналов, полученные из PassThruConnect/PassThruLogicalConnect
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() - Создание логического канала