Bus status evaluation of multiple channels
Posted: Mon 12. Aug 2024, 14:46
Maybe I misunderstand the conecept but the function GetCanBusStatus fails to retrieve the status of adapter #2 when initialized adapter #1 is unplugged. I use the UDS-API - the binding for Python and have installed the latest drivers 4.9.0.942. The version - read with GetValue_2013 - are:
I compiled a minimum example for Windows 10/11 that I tried out with two PCAN-USB adapters (IPEH-002022). The python script initializes adapter #1 (=device-id) and then enters a infinte loop to enumerate any adapters conected to the PC. To reproduce the problem:
Here is the minimum working example EDIT: I forgot two helper to_str functions:
Code: Select all
UDS API verison 2.3.1.295
ISO TP API verison 3.5.0.344
PCAN Basic API verison 4.9.0.942
- Connect two adapters to a Windows PC
- Run the script, in VSCode
- Initialization of adapter #1 should succeed (line "All Ok" in terminal)
- Enumeration should print "Adapter 1 BELEGT, all OK; Adapter 2 FREI, not initialized
- Unplug adapter 1 which is initialized
- I expected output: Adapter 2 FREI not initialized; but received output: Adapter 2 FREI Invalid cantp_handle
- Plug in adapter 1 again
- Enumeration prints idential (1 all OK, 2 not initialized)
- Click-focus terminal window, then press CTRL + C to exit infinte loop gracefully.
Here is the minimum working example EDIT: I forgot two helper to_str functions:
Code: Select all
#peak_adapter_enumeration.py - Python 3.11 - Windows 10 Enterprise 22H2 19045.4529
import time
import ctypes
import PCAN_UDS_2013 as puds
if __name__ == "__main__":
def adapter_to_str(adapter_handle : puds.TPCANHandle, include_index : bool = False):
"""returns readable name 'PCAN_USBBUS###' of specified handle"""
if adapter_handle is None:
return "NONE_SELECTED"
if isinstance(adapter_handle, puds.TPCANHandle):
adapter_handle = adapter_handle.value
# 1-8 [gap] [9-16] -> I hate it...
if adapter_handle == 0:
return "PCAN_NONEBUS"
# raise ValueError(f"Specified handle is zero due to a) contact issue (replug USB connector of adapter), b) wrong assignment (zero or PCAN_NONEBUS cannot be parsed)")
elif adapter_handle < puds.PCAN_USBBUS1.value:
raise ValueError(f"TPCANHandle, parsing error: invalid handle < PCAN_USBBUS1 (raw={adapter_handle}, hex={hex(adapter_handle)}).")
elif adapter_handle >= puds.PCAN_USBBUS1.value and adapter_handle <= puds.PCAN_USBBUS8.value:
return f"PCAN_USBBUS{adapter_handle - puds.PCAN_USBBUS1.value + 1}" + (f"({adapter_handle})" if include_index else "")
elif adapter_handle > puds.PCAN_USBBUS8.value and adapter_handle < puds.PCAN_USBBUS9.value:
raise ValueError(f"TPCANHandle, parsing error: WARNING, DEV(!): handles are not sequential, there is a gap between 1-8 and 9-16. use the PUDS_USBBUSxx constants or be careful. (raw={adapter_handle}, hex={hex(adapter_handle)}).")
elif adapter_handle >= puds.PCAN_USBBUS9.value and adapter_handle <= puds.PCAN_USBBUS16.value:
return f"PCAN_USBBUS{adapter_handle - puds.PCAN_USBBUS9.value + 9}" + (f"({adapter_handle})" if include_index else "")
else:
raise ValueError(f"TPCANHandle, parsing error: invalid handle > PCAN_USBBUS16 (raw={adapter_handle}, hex={hex(adapter_handle)}).")
def str_to_adapter(name : str):
"""returns TPCANHandle corresponding to readable string. Use together with ``generate_peak_adapter_string_list``"""
NUM_INTERFACE_CHANNELS = 16
try:
offset = int(name.split("PCAN_USBBUS")[1])
if offset < 1 or offset > NUM_INTERFACE_CHANNELS:
raise Exception(f"Cannot return TPCANHandle, invalid syntax. '{name} interface {offset} out of bounds 0 < x <= 16")
return puds.TPCANHandle(puds.PCAN_USBBUS1.value + offset - 1)
except (IndexError, ValueError) as iex:
raise Exception(f"Cannot return TPCANHandle, invalid syntax. '{name}' must begin with PCAN_USBBUS, and end with an integer value") from iex
def create_uds_tmp_buffer(template : Type, count : int) -> Any:
""""creates a temporary buffer of N structures (see PCAN_UDS_2013.py) that can be passed to GetValue_2013().
HINT: pass this buffer using ctypes' byref() method!"""
return (template * count)()
def enum_active_channels():
# use API function to get numer of active channels
nActiveChannels = ctypes.c_uint32()
uds.GetValue_2013(puds.PCAN_NONEBUS, puds.PCAN_ATTACHED_CHANNELS_COUNT, nActiveChannels, ctypes.sizeof(nActiveChannels))
# use API function to enumerate channels with detected adapters
activeDevices = create_uds_tmp_buffer(puds.TPCANChannelInformation, nActiveChannels.value)
retStatus = uds.GetValue_2013(puds.PCAN_NONEBUS, puds.PCAN_ATTACHED_CHANNELS, activeDevices, ctypes.sizeof(activeDevices))
return activeDevices
def get_error_text(status_in : puds.TPCANStatus):
tmpBuf = ctypes.create_string_buffer(256)
status = uds.GetErrorText_2013(status_in, 0, tmpBuf, ctypes.sizeof(tmpBuf)) # return c_type.c_long
return tmpBuf.value.decode("latin-1", errors='replace')
def get_api_version(api_parameter : puds.uds_parameter):
tmpBuf = ctypes.create_string_buffer(256)
status = uds.GetValue_2013(puds.PCAN_NONEBUS, api_parameter, tmpBuf, ctypes.sizeof(tmpBuf)) # return c_type.c_long
return tmpBuf.value.decode("latin-1", errors='replace')
#### START ####
uds = puds.PCAN_UDS_2013()
print("UDS API verison " + get_api_version(puds.PUDS_PARAMETER_API_VERSION))
print("ISO TP API verison " + get_api_version(puds.PCANTP_PARAMETER_API_VERSION))
print("PCAN Basic API verison " + get_api_version(puds.PCAN_API_VERSION))
print("###")
print(get_error_text(uds.Initialize_2013(puds.PCAN_USBBUS1, puds.PCAN_BAUD_500K)))
time.sleep(1.0)
try:
while True:
for ch in enum_active_channels():
bus_status = uds.GetCanBusStatus_2013(ch.channel_handle)
status_text = get_error_text(bus_status)
print(f"{adapter_to_str(ch.channel_handle)} - ID: {ch.device_id} - {channel_condition_to_str(ch.channel_condition)} - {status_text}")
pass
print("###########")
time.sleep(0.25)
except KeyboardInterrupt:
# click-focus "TERMINAL"-window in VSCode, then press CTRL + C
uds.Uninitialize_2013(puds.PCAN_NONEBUS)
print("END")