Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions can/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class CanOperationError(CanError):
- The driver rejected a message that was meant to be sent
- Cyclic redundancy check (CRC) failed
- A message remained unacknowledged
- A buffer is full
"""


Expand Down
64 changes: 31 additions & 33 deletions can/interfaces/socketcan/socketcan.py
Original file line number Diff line number Diff line change
Expand Up @@ -278,24 +278,19 @@ def send_bcm(bcm_socket: socket.socket, data: bytes) -> int:
"""
try:
return bcm_socket.send(data)
except OSError as e:
base = "Couldn't send CAN BCM frame. OS Error {}: {}\n".format(
e.errno, e.strerror
)

if e.errno == errno.EINVAL:
raise can.CanError(
base + "You are probably referring to a non-existing frame."
)

elif e.errno == errno.ENETDOWN:
raise can.CanError(base + "The CAN interface appears to be down.")

elif e.errno == errno.EBADF:
raise can.CanError(base + "The CAN socket appears to be closed.")

except OSError as error:
base = f"Couldn't send CAN BCM frame due to OS Error: {error.strerror}"

if error.errno == errno.EINVAL:
specific_message = " You are probably referring to a non-existing frame."
elif error.errno == errno.ENETDOWN:
specific_message = " The CAN interface appears to be down."
elif error.errno == errno.EBADF:
specific_message = " The CAN socket appears to be closed."
else:
raise e
specific_message = ""

raise can.CanOperationError(base + specific_message, error.errno) from error


def _compose_arbitration_id(message: Message) -> int:
Expand Down Expand Up @@ -330,7 +325,7 @@ def __init__(
messages: Union[Sequence[Message], Message],
period: float,
duration: Optional[float] = None,
):
) -> None:
"""Construct and :meth:`~start` a task.

:param bcm_socket: An open BCM socket on the desired CAN channel.
Expand Down Expand Up @@ -378,7 +373,7 @@ def _tx_setup(self, messages: Sequence[Message]) -> None:
log.debug("Sending BCM command")
send_bcm(self.bcm_socket, header + body)

def _check_bcm_task(self):
def _check_bcm_task(self) -> None:
# Do a TX_READ on a task ID, and check if we get EINVAL. If so,
# then we are referring to a CAN message with the existing ID
check_header = build_bcm_header(
Expand All @@ -394,14 +389,13 @@ def _check_bcm_task(self):
)
try:
self.bcm_socket.send(check_header)
except OSError as e:
if e.errno != errno.EINVAL:
raise e
except OSError as error:
if error.errno != errno.EINVAL:
raise can.CanOperationError("failed to check", error.errno) from error
else:
raise ValueError(
"A periodic task for Task ID {} is already in progress by SocketCAN Linux layer".format(
self.task_id
)
raise can.CanOperationError(
f"A periodic task for task ID {self.task_id} is already in progress "
"by the SocketCAN Linux layer"
)

def stop(self) -> None:
Expand Down Expand Up @@ -537,7 +531,7 @@ def capture_message(
else:
channel = None
except socket.error as error:
raise can.CanError(f"Error receiving: {error}")
raise can.CanOperationError(f"Error receiving: {error.strerror}", error.errno)

can_id, can_dlc, flags, data = dissect_can_frame(cf)

Expand All @@ -550,7 +544,7 @@ def capture_message(
# see https://man7.org/linux/man-pages/man3/timespec.3.html -> struct timespec for details
seconds, nanoseconds = RECEIVED_TIMESTAMP_STRUCT.unpack_from(cmsg_data)
if nanoseconds >= 1e9:
raise can.CanError(
raise can.CanOperationError(
f"Timestamp nanoseconds field was out of range: {nanoseconds} not less than 1e9"
)
timestamp = seconds + nanoseconds * 1e-9
Expand Down Expand Up @@ -716,9 +710,11 @@ def _recv_internal(
# get all sockets that are ready (can be a list with a single value
# being self.socket or an empty list if self.socket is not ready)
ready_receive_sockets, _, _ = select.select([self.socket], [], [], timeout)
except socket.error as exc:
except socket.error as error:
# something bad happened (e.g. the interface went down)
raise can.CanError(f"Failed to receive: {exc}")
raise can.CanOperationError(
f"Failed to receive: {error.strerror}", error.errno
)

if ready_receive_sockets: # not empty
get_channel = self.channel == ""
Expand Down Expand Up @@ -767,7 +763,7 @@ def send(self, msg: Message, timeout: Optional[float] = None) -> None:
data = data[sent:]
time_left = timeout - (time.time() - started)

raise can.CanError("Transmit buffer full")
raise can.CanOperationError("Transmit buffer full")

def _send_once(self, data: bytes, channel: Optional[str] = None) -> int:
try:
Expand All @@ -776,8 +772,10 @@ def _send_once(self, data: bytes, channel: Optional[str] = None) -> int:
sent = self.socket.sendto(data, (channel,))
else:
sent = self.socket.send(data)
except socket.error as exc:
raise can.CanError("Failed to transmit: %s" % exc)
except socket.error as error:
raise can.CanOperationError(
f"Failed to transmit: {error.strerror}", error.errno
)
return sent

def _send_periodic_internal(
Expand Down
2 changes: 1 addition & 1 deletion test/logformats_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def test_append_mode(self):
try:
writer = self.writer_constructor(self.test_file_name)
except TypeError:
# is the is still a problem, raise the initial error
# if it is still a problem, raise the initial error
raise e
with writer:
for message in second_part:
Expand Down
4 changes: 2 additions & 2 deletions test/test_cyclic_socketcan.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,10 +255,10 @@ def test_start_already_started_task(self):
time.sleep(0.1)

# Try to start it again, task_id is not incremented in this case
with self.assertRaises(ValueError) as ctx:
with self.assertRaises(can.CanOperationError) as ctx:
task_a.start()
self.assertEqual(
"A periodic task for Task ID 1 is already in progress by SocketCAN Linux layer",
"A periodic task for task ID 1 is already in progress by the SocketCAN Linux layer",
str(ctx.exception),
)

Expand Down