Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

slcan doesn't receive corresponding response after sending can message.

オープン
#2,060 コメント 3 件 リアクション 0 件 担当者 0 名 GitHub で見る

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
48/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
静か
技術スタック
python
領域
networking

調査の方向性

can.interfaces.slcan.slcanBus.send と recv から始め、次に報告された実装で使用されている _write と _read の呼び出しを調査します。CAN 配線を接続した状態と切断した状態で 2 台のデバイス構成を再現し、送信応答と同時受信の動作を確認します。成功した送信で ACKs が報告され、失敗した送信で BEL/NACK が報告され、送受信操作が競合したり誤ってブロックしたりしなければ完了です。

索引モデルが issue の本文から書いたものです。

説明

bug
Describe the bug

While calling slcanBus.send, the corresponding response isn't read. This makes it report false success even on failed messages.

To Reproduce

Setup two can devices, both configured to send ack on successful can message receive. Disconnect the can wires after some time.

Expected behavior

Expected to receive ack when wire is connected (slcan should report successful transmission)
Expected to receive nack(bel) when wire is disconnected (slcan should report failed transmission)

Additional context

OS and version: Ubuntu 24.04.3 LTS
Python version: Python 3.11.14
python-can version: 4.6.1
python-can interface/s: slcan with custom slcan device (esp32s3)

The following implementation solves that problem (introduces other ones)
import can
from can.interfaces.slcan import slcanBus
import threading


class SLCANBusWithErrorCheck(slcanBus):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._tx_lock = threading.Lock()

    def send(self, msg, timeout=None):
        if timeout != self.serialPortOrig.write_timeout:
            self.serialPortOrig.write_timeout = timeout

        if msg.is_remote_frame:
            if msg.is_extended_id:
                sendStr = f"R{msg.arbitration_id:08X}{msg.dlc:d}"
            else:
                sendStr = f"r{msg.arbitration_id:03X}{msg.dlc:d}"
        else:
            if msg.is_extended_id:
                sendStr = f"T{msg.arbitration_id:08X}{msg.dlc:d}"
            else:
                sendStr = f"t{msg.arbitration_id:03X}{msg.dlc:d}"
            sendStr += msg.data.hex().upper()

        with self._tx_lock:
            # Drain any leftover bytes from a previous error before sending
            self.serialPortOrig.reset_input_buffer()
            self._buffer.clear()

            self._write(sendStr)
            response = self._read(timeout=max(timeout or 0, 2.0))

        if response is None:
            raise can.CanError("TX timeout - no response from adapter")
        if self._ERROR.decode() in response:
            raise can.CanError("TX failed - BEL received (no ACK on bus)")

    def recv(self, timeout=None):
        if self._tx_lock.locked():
            return None
        return super().recv(timeout=timeout)

I know following are the errors in the provided solution:

  • If we are mid receive, then any call to send can create race condition (clear the serial buffers mid receive)
  • the timeout logic is also incorrect (additional 2.0 second for timeout < 2.0 second, patch for some other problem)
  • Receive fails immediately if transmission is going on

Any solution i came up for these problems seemed patchy as best. So, expecting it to solve inside of python-can itself or provide a better solution than locking.

主要言語
Python
スター
1.6k
フォーク
697
PR マージ指標
30日以内にマージされた PR はありません

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

hardbyte/python-can のほかの issue

hardbyte/python-can の issue をすべて見る

似ている issue

Python の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。