Skip to content

suppress_positive_response issue #279

Description

@jeffery96

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:

Image

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions