Skip to content

Commit 1236892

Browse files
authored
fix: Add 'UdsAuxiliary.send_uds' with clearer return type to replace 'send_uds_raw' (#561)
1 parent ce3dbf5 commit 1236892

6 files changed

Lines changed: 88 additions & 23 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ pip-delete-this-directory.txt
4343
# other logs
4444
*.log
4545
*.trc
46+
BrainStemLog.txt
4647

4748
# Unit test / coverage reports
4849
htmlcov/

docs/modules_usage/uds_auxiliary.rst

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ Find below a complete configuration example :
2626
com: can_channel
2727
config:
2828
# you can specify your odx file by using odx_file_path parameter
29-
# and instead of using send_uds_raw method use the send_uds_config
29+
# and instead of using send_uds method use the send_uds_config
3030
# for a more human readable command
3131
odx_file_path: null
3232
request_id : 0x123
@@ -75,14 +75,10 @@ Send UDS Raw Request
7575

7676
Send UDS request as list of raw bytes.
7777

78-
The method send_uds_raw(:py:meth:`pykiso.lib.auxiliaries.udsaux.UdsAuxiliary.send_uds_raw`) takes one mandatory parameter msg_to_send and one optional : timeout_in_s
78+
The method send_uds(:py:meth:`pykiso.lib.auxiliaries.udsaux.UdsAuxiliary.send_uds`) takes one mandatory parameter msg_to_send
7979
The parameter msg_to_send is simply the UDS request payload which is a list of bytes.
8080

81-
The optional parameter timeout_in_s (by default fixed to 5 seconds) simply represent the maximum
82-
amount of time in second to wait for a response from the device under test. If this timeout is reached, the
83-
uds-auxiliary stop to acquire and log an error.
84-
85-
The method send_uds_raw method returns a :py:class:`~ebplugins.udsaux.uds_response.UdsResponse` object, which is a subclass of `UserList
81+
The method send_uds method returns a :py:class:`~ebplugins.udsaux.uds_response.UdsResponse` object, which is a subclass of `UserList
8682
<https://docs.python.org/3/library/collections.html#collections.UserList>`_.
8783
UserList allow to keep property of the list, meanwhile attributes can be set, for UdsResponse, defined attributes
8884
refer to the positivity of the response, and its NRC if negative.
@@ -117,7 +113,7 @@ Here is an example:
117113
118114
def test_run(self):
119115
# Set extended session
120-
diag_session_response = uds_aux.send_uds_raw([0x10, 0x03])
116+
diag_session_response = uds_aux.send_uds([0x10, 0x03])
121117
self.assertEqual(diag_session_response[:2], [0x50, 0x03])
122118
self.assertEqual(type(diag_session_response), UserList)
123119
self.assertFalse(diag_session_response.is_negative)

docs/whats_new/version_1_6_0.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
Version 1.6.0
2+
-------------
3+
4+
Better return type when sending UDS messages
5+
^^^^^^^^^^^^^^^^^
6+
7+
New method `UdsAuxiliary.send_uds`, available in two versions (`typing.overload`):
8+
- when expecting a response (`response_required=True`) from remote component, returns the response,
9+
or fails with an exception
10+
- otherwise, return `None`, or fail with an exception
11+
12+
This is more in line with what exising clients expected.
13+
14+
The previous version of this method, `UdsAuxiliary.send_uds_raw`, has been kept with the same API,
15+
for backwards compatibility: return `False` on error, unless the error is because no response
16+
was received while one was expected, in which case a `ReponseNotReceivedException` is raised.
17+
18+
19+
See :ref:`uds_server_auxiliary`

examples/uds.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ auxiliaries:
44
com: can_channel
55
config:
66
# you can specify your odx file by using odx_file_path parameter
7-
# and instead of using send_uds_raw method use the send_uds_config
7+
# and instead of using send_uds method use the send_uds_config
88
# for a more human readable command
99
odx_file_path: ~
1010
request_id : 0x123

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "pykiso"
3-
version = "1.5.2"
3+
version = "1.6.0"
44
description = "Embedded integration testing framework."
55
authors = ["Sebastian Fischer <sebastian.fischer@de.bosch.com>"]
66
license = "Eclipse Public License - v 2.0"

src/pykiso/lib/auxiliaries/udsaux/uds_auxiliary.py

Lines changed: 62 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import time
2424
from contextlib import contextmanager
2525
from pathlib import Path
26-
from typing import Iterator, List, Optional, Union
26+
from typing import Iterator, List, Literal, Optional, Union, overload
2727

2828
try:
2929
import can
@@ -90,26 +90,46 @@ def transmit(self, data: bytes, req_id: int, extended: bool = False) -> None:
9090
"""
9191
self.channel._cc_send(msg=data, remote_id=req_id)
9292

93-
def send_uds_raw(
93+
# Response is required, it is returned
94+
@overload
95+
def send_uds(
96+
self,
97+
msg_to_send: Union[bytes, List[int], tuple],
98+
) -> UdsResponse:
99+
... # pragma: no cover
100+
101+
# Response is required, it is returned (explicit alias kept for backwards compatibility)
102+
@overload
103+
def send_uds(
104+
self,
105+
msg_to_send: Union[bytes, List[int], tuple],
106+
response_required: Literal[True] = True,
107+
) -> UdsResponse:
108+
... # pragma: no cover
109+
110+
# Response ignored, `None` is returned
111+
@overload
112+
def send_uds(
113+
self,
114+
msg_to_send: Union[bytes, List[int], tuple],
115+
response_required: Literal[False] = False,
116+
) -> None:
117+
... # pragma: no cover
118+
119+
def send_uds(
94120
self,
95121
msg_to_send: Union[bytes, List[int], tuple],
96-
timeout_in_s: float = 6,
97122
response_required: bool = True,
98-
) -> Union[UdsResponse, bool]:
123+
) -> Union[UdsResponse, None]:
99124
"""Send a UDS diagnostic request to the target ECU and check response.
100125
101126
:param msg_to_send: can uds raw bytes to be sent
102-
:param timeout_in_s: not used, actual timeout in seconds for the response can be
103-
configured with the uds_aux.config.uds_layer.p2_can_client parameter
104-
inside the yaml config file. (default value is 5s)
105127
:param response_required: Wait for a response if True
106128
107129
:raise ResponseNotReceivedError: raised when no answer has been received
108130
:raise Exception: raised when the raw message could not be send properly
109131
110-
:return: the raw uds response's bytes, or True if a response is
111-
not expected and the command is properly sent otherwise
112-
False
132+
:return: the raw uds response's bytes if `response_required` is set, else None
113133
"""
114134
try:
115135
if log.isEnabledFor(logging.getLogger().level):
@@ -122,13 +142,13 @@ def send_uds_raw(
122142
responseRequired=response_required,
123143
tpWaitTime=self.tp_waiting_time,
124144
)
125-
except Exception:
145+
except Exception as exc:
126146
log.exception("Error while sending uds raw request")
127-
return False
147+
raise exc
128148

129149
if resp is None:
130150
if not response_required:
131-
return True
151+
return
132152
else:
133153
raise self.errors.ResponseNotReceivedError(msg_to_send)
134154

@@ -140,6 +160,35 @@ def send_uds_raw(
140160
log.internal_info("UDS response received %s", resp)
141161
return resp
142162

163+
def send_uds_raw(
164+
self,
165+
msg_to_send: Union[bytes, List[int], tuple],
166+
timeout_in_s: float = 6,
167+
response_required: bool = True,
168+
) -> Union[UdsResponse, bool]:
169+
"""Send a UDS diagnostic request to the target ECU and check response.
170+
Deprecated alias of `send_uds` that returns `False` on error,
171+
kept for backwards compatibility
172+
173+
:param msg_to_send: can uds raw bytes to be sent
174+
:param timeout_in_s: not used, actual timeout in seconds for the response can be
175+
configured with the uds_aux.config.uds_layer.p2_can_client parameter
176+
inside the yaml config file. (default value is 5s)
177+
:param response_required: Wait for a response if True
178+
179+
:raise ResponseNotReceivedError: raised when no answer has been received
180+
181+
:return: the raw uds response's bytes, or True if a response is
182+
not expected and the command is properly sent otherwise
183+
False
184+
"""
185+
try:
186+
return True if (response := self.send_uds(msg_to_send, response_required)) is None else response
187+
except self.errors.ResponseNotReceivedError as exc:
188+
raise exc
189+
except Exception:
190+
return False
191+
143192
@staticmethod
144193
def check_max_pending_time(resp: UdsResponse, max_pending_time: float) -> bool:
145194
"""Check that the time between pending response messages does not exceed a

0 commit comments

Comments
 (0)