pylessard / python-udsoncan

Python implementation of UDS (ISO-14229) standard.
MIT License
578 stars 199 forks source link

udsoncan.exceptions.TimeoutException: Did not receive response in time. P2 timeout time has expired (timeout=1.000 sec) #115

Closed catmemo closed 2 years ago

catmemo commented 2 years ago

Please check below issue:

2022-03-25 16:52:14 [INFO] Connection: Connection opened
2022-03-25 16:52:14 [INFO] UdsClient: DiagnosticSessionControl<0x10> - Switching session to extendedDiagnosticSession (0x03)
2022-03-25 16:52:14 [DEBUG] Connection: Sending 2 bytes : [b'1003']
2022-03-25 16:52:14 [DEBUG] Connection: Received 6 bytes : [b'5003003200c8']
2022-03-25 16:52:14 [INFO] UdsClient: Received positive response for service DiagnosticSessionControl (0x10) from server.
2022-03-25 16:52:14 [INFO] Connection: Connection closed
2022-03-25 16:52:14 [INFO] Connection: Connection opened
2022-03-25 16:52:14 [INFO] UdsClient: TesterPresent<0x3e> - Sending TesterPresent request
2022-03-25 16:52:14 [INFO] Connection: Connection opened
2022-03-25 16:52:14 [DEBUG] Connection: Sending 2 bytes : [b'3e00']
2022-03-25 16:52:14 [INFO] UdsClient: RoutineControl<0x31> - ControlType=0x01 - Starting routine ID 0x0203 (VehicleManufacturerSpecific) with a payload of 0 bytes
2022-03-25 16:52:14 [DEBUG] Connection: Sending 4 bytes : [b'31010203']
2022-03-25 16:52:14 [DEBUG] Connection: Received 2 bytes : [b'7e00']
2022-03-25 16:52:14 [INFO] UdsClient: Received positive response for service TesterPresent (0x3e) from server.
2022-03-25 16:52:14 [INFO] Connection: Connection closed
2022-03-25 16:52:15 [DEBUG] Connection: No data received: [TimeoutException] - Did not receive frame IsoTP Transport layer in time (timeout=1 sec) 
2022-03-25 16:52:15 [ERROR] UdsClient: [TimeoutException] : Did not receive response in time. P2 timeout time has expired (timeout=1.000 sec)
2022-03-25 16:52:15 [INFO] Connection: Connection closed
Traceback (most recent call last):
  File "D:\Development_Tools\Python\lib\site-packages\udsoncan\client.py", line 1647, in send_request
    payload = self.conn.wait_frame(timeout=timeout_value, exception=True)   
  File "D:\Development_Tools\Python\lib\site-packages\udsoncan\connections.py", line 68, in wait_frame
    frame = self.specific_wait_frame(timeout=timeout)
  File "D:\Development_Tools\Python\lib\site-packages\udsoncan\connections.py", line 490, in specific_wait_frame
    raise TimeoutException("Did not receive frame IsoTP Transport layer in time (timeout=%s sec)" % timeout)
udsoncan.exceptions.TimeoutException: Did not receive frame IsoTP Transport layer in time (timeout=1 sec)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:/Live_And_Learn/Python/flash/flash_gac/main.py", line 41, in <module>
    if not send_routine_control_command(0x0203) == b'\x01\x02\x03':
  File "D:\Live_And_Learn\Python\flash\flash_gac\Send_Diag_Command.py", line 251, in send_routine_control_command
    routine_response = client.start_routine(routine_id, data)
  File "D:\Development_Tools\Python\lib\site-packages\udsoncan\client.py", line 527, in start_routine
    return self.routine_control(routine_id, services.RoutineControl.ControlType.startRoutine, data)
  File "D:\Development_Tools\Python\lib\site-packages\udsoncan\client.py", line 131, in decorated
    return func(self, *args, **kwargs)
  File "D:\Development_Tools\Python\lib\site-packages\udsoncan\client.py", line 600, in routine_control
    response = self.send_request(request)
  File "D:\Development_Tools\Python\lib\site-packages\udsoncan\client.py", line 1655, in send_request
    raise TimeoutException('Did not receive response in time. %s time has expired (timeout=%.3f sec)' % (timeout_name_to_report, timeout_value))
udsoncan.exceptions.TimeoutException: Did not receive response in time. P2 timeout time has expired (timeout=1.000 sec)

my Send_Diag_Command.py

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
    'll_data_length': 8,  # Link layer (CAN layer) works with 8 byte payload (CAN 2.0)
    'tx_padding': 0,  # Will pad all transmitted CAN messages with byte 0x00. None means no padding
    'rx_flowcontrol_timeout': 2000,  # Triggers a timeout if a flow control is awaited for more than 1000 milliseconds
    'rx_consecutive_frame_timeout': 2000,  # Triggers a timeout if a consecutive frame is awaited for more than 1000 milliseconds
    'squash_stmin_requirement': False  # When sending, respect the stmin requirement of the receiver. If set to True, go as fast as possible.
}
global config
config = dict(udsoncan.configs.default_client_config)

config['data_identifiers'] = {
    0xF186: udsoncan.AsciiCodec(1),
}
config['use_server_timing'] = False
config['p2_timeout '] = 5
config['p2_star_timeout '] = 5
config['request_timeout '] = 5

tp_addr = isotp.Address(isotp.AddressingMode.Normal_11bits, txid=0x72b, rxid=0x7ab)
stack = isotp.CanStack(bus=bus, address=tp_addr, params=isotp_params) 
global conn
conn = PythonIsoTpConnection(stack)

def send_diag_session_control(session):

    with Client(conn, request_timeout=10, config=config) as client:
        try:
            if session == "10/01":
                client.change_session(DiagnosticSessionControl.Session.defaultSession)

            elif session == "10/03":
                session_response = client.change_session(DiagnosticSessionControl.Session.extendedDiagnosticSession)
                return session_response.data

        except NegativeResponseException as e:
            print('Server refused our request for service %s with code "%s" (0x%02x)' % (e.response.service.get_name(), e.response.code_name, e.response.code))

        except (InvalidResponseException, UnexpectedResponseException) as e:
            print('Server sent an invalid payload : %s' % e.response.original_payload)

def send_diag_read_command(command):

    with Client(conn, request_timeout=2, config=config) as client:
        try:
            command = int(command, 16)
            response = client.read_data_by_identifier(command)
            return response.data

        except NegativeResponseException as e:
            print('Server refused our request for service %s with code "%s" (0x%02x)' % (e.response.service.get_name(), e.response.code_name, e.response.code))

        except (InvalidResponseException, UnexpectedResponseException) as e:
            print('Server sent an invalid payload : %s' % e.response.original_payload)

def send_tester_present_command():

   with Client(conn,  request_timeout=2, config=config) as client:

       try:
           client.tester_present()

       except NegativeResponseException as e:
         print('Server refused our request for service %s with code "%s" (0x%02x)' % (e.response.service.get_name(), e.response.code_name, e.response.code))

       except (InvalidResponseException, UnexpectedResponseException) as e:
         print('Server sent an invalid payload : %s' % e.response.original_payload)

and my main.py:

import threading
from Send_Diag_Command import *

def send_regular_tester_present():

    while True:
        send_tester_present_command()
        time.sleep(2)

if not send_diag_session_control('10/03')[0] == 3:
    time.sleep(1000000)

tester_thread = threading.Thread(target=send_regular_tester_present, args=())
tester_thread.start()

if not send_routine_control_command(0x0203) == b'\x01\x02\x03':
    time.sleep(1000000)

Could you please help to check? Any questions please let me know, thanks~

pylessard commented 2 years ago

It looks like you have 3 different client that uses the same connection. When the client exit, at the end of the with block, the connection is closed and the other clients can't use the conenction. You should have a global client instead of a global connection. Open the client (and the connection) at the beggining of the program, and exit then client at the very end. Everything in between will use the client.

Since you seem to be using threads, you will need to ensure that the client is not waiting for a response before sending a request. Mutex will be needed here.

catmemo commented 2 years ago

OK, I'll try, thank you very much!