-
-
Couldn't load subscription status.
- Fork 221
Description
I’m implementing uds bootloader. Some of the request services use functional addressing, but the following exceptions occur during actual operation.
I checked the actual data on the bus and the response from the ECU feedback was actually correct.
The strange thing is that when I try many times, sometimes it is normal, sometimes it is abnormal, and every time there is an abnormality, the unexpected ID that I receive is 0x68.
Here is my code:
import time
import can
from ZlgCan import ZlgCanBus
from udsoncan.connections import PythonIsoTpConnection
from udsoncan.client import Client
import udsoncan.configs
import isotp
isotp_params = {
'stmin': 32,
# Will request the sender to wait 32ms between consecutive frame. 0-127ms or 100-900ns with values from 0xF1-0xF9
'blocksize': 8, # Request the sender to send 8 consecutives frames before sending a new flow control message
'wftmax': 0, # Number of wait frame allowed before triggering an error
'tx_data_length': 8, # Link layer (CAN layer) works with 8 byte payload (CAN 2.0)
# Minimum length of CAN messages. When different from None, messages are padded to meet this length. Works with CAN 2.0 and CAN FD.
'tx_data_min_length': None,
'tx_padding': 0x55, # Will pad all transmitted CAN messages with byte 0x00.
'rx_flowcontrol_timeout': 1000, # Triggers a timeout if a flow control is awaited for more than 1000 milliseconds
'rx_consecutive_frame_timeout': 1000,
# Triggers a timeout if a consecutive frame is awaited for more than 1000 milliseconds
'override_receiver_stmin': None, # When sending, respect the stmin requirement of the receiver. If set to True, go as fast as possible.
'max_frame_size': 4095, # Limit the size of receive frame.
'can_fd': False, # Does not set the can_fd flag on the output CAN messages
'bitrate_switch': False, # Does not set the bitrate_switch flag on the output CAN messages
'rate_limit_enable': False, # Disable the rate limiter
'rate_limit_max_bitrate': 1000000,
# Ignored when rate_limit_enable=False. Sets the max bitrate when rate_limit_enable=True
'rate_limit_window_size': 0.2,
# Ignored when rate_limit_enable=False. Sets the averaging window size for bitrate calculation when rate_limit_enable=True
'listen_mode': False, # Does not use the listen_mode which prevent transmission.
}
def security_algo(level:int, seed:bytes, params):
print('Call security_algo...')
seed = int.from_bytes(seed, 'big')
r = [0x64, 0x6a, 0x71, 0x25, 0x35, 0x63, 0x75, 0x23]
key = 0
for i in range(4):
temp = ((seed >> (i * 8)) & 0xff) + r[i]
temp = temp & 0xff # python变量64位无溢出,需要处理
# print(hex(r[i]), hex(temp), hex((seed >> (i * 8)) & 0xff))
key = (temp << (i * 8)) | key
seed ^= 0x5A5A5A5A
return key.to_bytes(4, 'big')
udsoncan.setup_logging()
uds_config = udsoncan.configs.default_client_config.copy()
uds_config['use_server_timing'] = False
# uds_config['request_timeout'] = None
uds_config['security_algo'] = security_algo
uds_config['data_identifiers'] = {
0xF190: udsoncan.AsciiCodec(4) # Codec that read ASCII string. We must tell the length of the string
}
filters = [
# {"can_id": 0x18FFFF02, "can_mask": 0x1FFFFFFF, "extended": True},
{"can_id": 0x700, "can_mask": 0xFFFF, "extended": False},
{"can_id": 0x701, "can_mask": 0xFFFF, "extended": False},
{"can_id": 0x7DF, "can_mask": 0xFFFF, "extended": False},
]
# bus = PcanBus(bitrate=250000) # Link Layer (CAN protocol)
bus = ZlgCanBus("USBCAN-II", 0, 0, "250K", can_filters=filters)
time.sleep(0.2) # Run会引发从tp层接收空的异常,而debug不会,怀疑可能Pcan初始化时间长,需要等待硬件初始化完成,加入延时等待后问题解决,可能由于盗版Pcan导致 - lxb 2024/5/17
file_to_write = open(file='./test.asc', mode='w+', encoding='utf-8')
# notifier = can.Notifier(bus, [can.Printer(), can.ASCWriter(file_to_write)]) # Add a debug listener that print all messages
notifier = can.Notifier(bus, [can.ASCWriter(file_to_write)])
tp_addr = isotp.Address(isotp.AddressingMode.Normal_11bits, txid=0x700, rxid=0x701) # Network layer addressing scheme
# stack = isotp.CanStack(bus=bus, address=tp_addr, params=isotp_params) # isotp v1.x has no notifier support
stack = isotp.NotifierBasedCanStack(bus=bus, notifier=notifier, address=tp_addr, params=isotp_params) # Network/Transport layer (IsoTP protocol). Register a new listenenr
conn = PythonIsoTpConnection(stack) # interface between Application and Transport layer
def tp_layer_change_address_type(address_type):
if address_type == 'Functional':
print('切换功能寻址...')
stack.params.set('default_target_address_type', isotp.address.TargetAddressType.Functional)
new_tp_addr = isotp.Address(isotp.AddressingMode.Normal_11bits, txid=0x7DF, rxid=0x701)
stack.set_address(new_tp_addr)
elif address_type == 'Physical':
print('切换物理寻址...')
stack.params.set('default_target_address_type', isotp.address.TargetAddressType.Physical)
new_tp_addr = isotp.Address(isotp.AddressingMode.Normal_11bits, txid=0x700, rxid=0x701)
stack.set_address(new_tp_addr)
else:
print('无效UDS地址...')
pass
with Client(conn, config=uds_config) as client: # Application layer (UDS protocol)
################################ 预编程阶段 ################################
tp_layer_change_address_type('Physical') # 切换至功能寻址
client.change_session(3) # 切换至扩展会话
tp_layer_change_address_type('Physical')
# client.start_routine(0x0203) # 例程控制检查编程条件
tp_layer_change_address_type('Functional') # 切换至功能寻址
with client.suppress_positive_response:
client.control_dtc_setting(1)
client.communication_control(1, 3) # 禁止非诊断报文的发送和接收,功能寻址情况下ECU不发送响应,会引起未接收到响应异常
################################ 主编程阶段 ################################
tp_layer_change_address_type('Physical')
client.change_session(2) # 切换至编程会话
client.unlock_security_access(1) # 安全访问
client.write_data_by_identifier(0xF190, 'DEAD') # 写入刷写时间
# client.write_data_by_identifier(0xF199, 0xBEEF) # 写入指纹
client.start_routine(0xFF00, b'\xA0\x02\x00\x00') # 例程控制擦除内存
# 请求下载
memory_location = udsoncan.MemoryLocation(0xA0020000, 32, None, None)
client.request_download(memory_location, None)
# 传输数据
data1 = bytes([0x00, 0xa0, 0x3c, 0xff, 0x20, 0x20, 0x20, 0x20, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
data2 = bytes([0x91, 0x20, 0x00, 0xf8, 0xd9, 0xff, 0xf2, 0xc1, 0xdc, 0x0f, 0x00, 0x90, 0xff, 0xff, 0xff, 0xff,
0x32, 0x56, 0xff, 0x06, 0x26, 0x00, 0x3b, 0x00, 0xfe, 0xff, 0x3f, 0xf6, 0x17, 0x00, 0x0f, 0x65])
client.transfer_data(0x00, data1)
# 请求退出传输
# 检查APP正确性、完整性
data = [data1, data2]
# for i in range(1, 3, 1):
# client.transfer_data(i, data[i-1])
# with open('./test.bin', 'rb') as f:
# # 获取bin文件大小
# import os
# size = f.seek(0, os.SEEK_END)
# f.seek(0)
# block_sequence = 1
#
# for idx in range(int(size/32)):
# if block_sequence >= 0xff:
# block_sequence = 1
# else:
# block_sequence += 1
#
# client.transfer_data(block_sequence, f.read(32))
# while True:
# pass
# ...
################################ 后编程阶段 ################################
file_to_write.close()
if __name__ == '__main__':
# security_algo(1, b'\xaa\xbb\xcc\xdd', 1)
pass
And here is the CAN data when exception occured:
Here is exception info:
2025-06-23 11:31:46 [INFO] Connection: Connection opened
切换物理寻址...
2025-06-23 11:31:46 [INFO] UdsClient: DiagnosticSessionControl<0x10> - Switching session to extendedDiagnosticSession (0x03)
2025-06-23 11:31:46 [DEBUG] Connection: Sending 2 bytes : [1003]
2025-06-23 11:31:46 [DEBUG] Connection: Received 6 bytes : [500300320190]
2025-06-23 11:31:46 [INFO] UdsClient: Received positive response for service DiagnosticSessionControl (0x10) from server.
切换物理寻址...
切换功能寻址...
2025-06-23 11:31:46 [INFO] UdsClient: ControlDTCSetting<0x85> - SettingType=0x01 (on) - Turning DTC On with a payload of 0 bytes
2025-06-23 11:31:46 [DEBUG] Connection: Sending 2 bytes : [8581]
2025-06-23 11:31:46 [INFO] UdsClient: CommunicationControl<0x28> - ControlType=0x01 (enableRxAndDisableTx) - Sending request with a CommunicationType byte of 0x03 (subnet=0x0. Flags : [NormalMsg,NetworkManagementMsg]). nodeIdentificationNumber=None
2025-06-23 11:31:46 [DEBUG] Connection: Sending 3 bytes : [288103]
切换物理寻址...
2025-06-23 11:31:46 [INFO] UdsClient: DiagnosticSessionControl<0x10> - Switching session to programmingSession (0x02)
2025-06-23 11:31:46 [DEBUG] Connection: Sending 2 bytes : [1002]
2025-06-23 11:31:46 [DEBUG] Connection: Received 3 bytes : [7f2812]
2025-06-23 11:31:46 [ERROR] UdsClient: [UnexpectedResponseException] : CommunicationControl service execution returned a valid response but unexpected. Details : Response gotten from server has a service ID different than the request service ID. Received=0x68, Expected=0x50
Traceback (most recent call last):
File "F:\00_Workspace\00_Python\UDSonCAN_Test_0_1\UdsTest.py", line 115, in
client.change_session(2) # 切换至编程会话
File "F:\00_Workspace\00_Python\UDSonCAN_Test_0_1.venv\lib\site-packages\udsoncan\client.py", line 175, in decorated
return func(self, *args, **kwargs)
File "F:\00_Workspace\00_Python\UDSonCAN_Test_0_1.venv\lib\site-packages\udsoncan\client.py", line 242, in change_session
response = self.send_request(req)
File "F:\00_Workspace\00_Python\UDSonCAN_Test_0_1.venv\lib\site-packages\udsoncan\client.py", line 2310, in send_request
raise UnexpectedResponseException(response, msg)
udsoncan.exceptions.UnexpectedResponseException: CommunicationControl service execution returned a valid response but unexpected. Details : Response gotten from server has a service ID different than the request service ID. Received=0x68, Expected=0x50
2025-06-23 11:31:46 [INFO] Connection: Connection closed
