From 6de1b8a5722f494fddc3d835f29af494cb64dc45 Mon Sep 17 00:00:00 2001 From: Yegor Yefremov Date: Wed, 22 Aug 2018 14:00:39 +0200 Subject: [PATCH] serial: switch to serial_for_url instead of Serial This way one can also use remote ports via socket:// or rfc2217:// URLs. --- can/interfaces/serial/serial_can.py | 3 ++- can/interfaces/slcan.py | 3 ++- doc/interfaces/serial.rst | 4 +++ doc/interfaces/slcan.rst | 8 +++--- test/serial_test.py | 38 +++++++++++++++++++---------- 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/can/interfaces/serial/serial_can.py b/can/interfaces/serial/serial_can.py index 0184d2abc..c71b8a602 100644 --- a/can/interfaces/serial/serial_can.py +++ b/can/interfaces/serial/serial_can.py @@ -54,7 +54,8 @@ def __init__(self, channel, baudrate=115200, timeout=0.1, *args, **kwargs): raise ValueError("Must specify a serial port.") self.channel_info = "Serial interface: " + channel - self.ser = serial.Serial(channel, baudrate=baudrate, timeout=timeout) + self.ser = serial.serial_for_url( + channel, baudrate=baudrate, timeout=timeout) super(SerialBus, self).__init__(channel=channel, *args, **kwargs) diff --git a/can/interfaces/slcan.py b/can/interfaces/slcan.py index 26f3bb36f..d30bcdd8e 100755 --- a/can/interfaces/slcan.py +++ b/can/interfaces/slcan.py @@ -65,7 +65,8 @@ def __init__(self, channel, ttyBaudrate=115200, timeout=1, bitrate=None, **kwarg if '@' in channel: (channel, ttyBaudrate) = channel.split('@') - self.serialPortOrig = serial.Serial(channel, baudrate=ttyBaudrate, timeout=timeout) + self.serialPortOrig = serial.serial_for_url( + channel, baudrate=ttyBaudrate, timeout=timeout) time.sleep(self._SLEEP_AFTER_SERIAL_OPEN) diff --git a/doc/interfaces/serial.rst b/doc/interfaces/serial.rst index 8335b39eb..413d9cfd1 100644 --- a/doc/interfaces/serial.rst +++ b/doc/interfaces/serial.rst @@ -4,6 +4,10 @@ CAN over Serial =============== A text based interface. For example use over serial ports like ``/dev/ttyS1`` or ``/dev/ttyUSB0`` on Linux machines or ``COM1`` on Windows. +Remote ports can be also used via a special URL. Both raw TCP sockets as +also RFC2217 ports are supported: ``socket://192.168.254.254:5000`` or +``rfc2217://192.168.254.254:5000``. In addition a virtual loopback can be +used via ``loop://`` URL. The interface is a simple implementation that has been used for recording CAN traces. diff --git a/doc/interfaces/slcan.rst b/doc/interfaces/slcan.rst index 242d2983c..de182e8b8 100755 --- a/doc/interfaces/slcan.rst +++ b/doc/interfaces/slcan.rst @@ -5,10 +5,12 @@ CAN over Serial / SLCAN A text based interface: compatible to slcan-interfaces (slcan ASCII protocol) should also support LAWICEL direct. These interfaces can also be used with socketcan and slcand with Linux. -This driver directly uses the serial port, it makes slcan-compatible interfaces usable with Windows also. +This driver directly uses either the local or remote serial port, it makes slcan-compatible interfaces usable with Windows also. +Remote serial ports will be specified via special URL. Both raw TCP sockets as also RFC2217 ports are supported. -Usage: use ``port[@baurate]`` to open the device. -For example use ``/dev/ttyUSB0@115200`` or ``COM4@9600`` +Usage: use ``port or URL[@baurate]`` to open the device. +For example use ``/dev/ttyUSB0@115200`` or ``COM4@9600`` for local serial ports and +``socket://192.168.254.254:5000`` or ``rfc2217://192.168.254.254:5000`` for remote ports. .. note: An Arduino-Interface could easily be build with this: diff --git a/test/serial_test.py b/test/serial_test.py index 1c189e4fb..da67cfaa2 100644 --- a/test/serial_test.py +++ b/test/serial_test.py @@ -36,21 +36,9 @@ def reset(self): self.msg = None -class SimpleSerialTest(unittest.TestCase): +class SimpleSerialTestBase(object): MAX_TIMESTAMP = 0xFFFFFFFF / 1000 - def setUp(self): - self.patcher = patch('serial.Serial') - self.mock_serial = self.patcher.start() - self.serial_dummy = SerialDummy() - self.mock_serial.return_value.write = self.serial_dummy.write - self.mock_serial.return_value.read = self.serial_dummy.read - self.addCleanup(self.patcher.stop) - self.bus = SerialBus('bus') - - def tearDown(self): - self.serial_dummy.reset() - def test_rx_tx_min_max_data(self): """ Tests the transfer from 0x00 to 0xFF for a 1 byte payload @@ -136,5 +124,29 @@ def test_rx_tx_min_timestamp_error(self): self.assertRaises(ValueError, self.bus.send, msg) +class SimpleSerialTest(unittest.TestCase, SimpleSerialTestBase): + + def setUp(self): + self.patcher = patch('serial.Serial') + self.mock_serial = self.patcher.start() + self.serial_dummy = SerialDummy() + self.mock_serial.return_value.write = self.serial_dummy.write + self.mock_serial.return_value.read = self.serial_dummy.read + self.addCleanup(self.patcher.stop) + self.bus = SerialBus('bus') + + def tearDown(self): + self.serial_dummy.reset() + + +class SimpleSerialLoopTest(unittest.TestCase, SimpleSerialTestBase): + + def setUp(self): + self.bus = SerialBus('loop://') + + def tearDown(self): + self.bus.shutdown() + + if __name__ == '__main__': unittest.main()