TCP to Serial Bridge

It’s useful to be able to connect to a piece of rfblocks hardware from anywhere on a given network. As an example of this, suppose that a USB hub is connected to some host computer on the network. rfblocks control hardware can now be plugged into the hub and USB/RS-232 style serial connections can be made to the serial devices associated with the hub. In order to allow connections from other hosts on the network an instance of the TCP to serial bridge is started on the host with the USB hub. Connections can now be made remotely to the rfblocks hardware via this bridge.

_images/distributedControl.svg

Figure 1 TCP to serial bridge in a networked environment

Bridge configuration

The bridge configuration is a set of pySerial device and baudrate pairs which specify the available USB/RS-232 devices on the host where the bridge instance is running. The configuration can be specified on the command line or, perhaps more conveniently, as a JSON formatted configuration file.

The bridge accepts a JSON formatted configuration containing information about possible rfblocks module assemblies or controllers which may be connected to the host. The configuration is structured as a JSON dictionary with each device represented by its USB serial number.

Here is an example entry in the bridge configuration file:

"E660583883668232":
{
    "port": 7009,
    "baudrate": null,
    "description": "Low Spur. RF Gen",
    "application": "LowSpuriousRFGen/app/rfgen.py",
    "app_args": "-D LowSpuriousRFGen/app/spur_data.csv"
},
port

The TCP port number where the device will be available. When accessing the device using pySerial the device URL would be: socket://1.2.3.4:7009.

baudrate

The baudrate for the device or null if the default baudrate (1.5 Mbit/sec) can be used.

description

A short text description of the device.

application

File path for the application which should be used to control this device.

app_args

Any command line arguments which should be passed to the application.

Note that the description, application, and app_args parameters are optional but must be present if the rfblocks application launcher is being used.

On Linux the serial number of a connected USB device can be found using:

$ lsusb
...
Bus 001 Device 011: ID 2e8a:000a Raspberry Pi Pico
...

$ lsusb -v -s 001:011 | grep -E "@|iManufacturer|iProduct|iSerial"

with example output as follows:

iManufacturer           1 Raspberry Pi
iProduct                2 Pico
iSerial                 3 E660D4A0A7565638

On MacOS the serial number is found using:

$ ioreg -p IOUSB -l -b | grep -E "@|PortNum|USB Serial Number"

with example output as follows:

+-o AppleUSBXHCI Root Hub Simulation@14000000  <class AppleUSBRootHubDevice, id 0x100000357, registered, matched, active, busy 0 (3 ms), retain 10>
+-o Bluetooth USB Host Controller@14300000  <class AppleUSBDevice, id 0x100006852, registered, matched, active, busy 0 (0 ms), retain 21>
|     "PortNum" = 3
+-o Pico@14200000  <class AppleUSBDevice, id 0x100006d48, registered, matched, active, busy 0 (2 ms), retain 15>
      "USB Serial Number" = "E660D4A0A7565638"
      "PortNum" = 2

Command line usage

usage: bridge.py [-h] [-l] [-I IPADDR] [-P IPPORT] [-p RPYC_PORT] [-C CONFIG] [devices [devices ...]]

rfblocks TCP to serial bridge.

positional arguments:
  devices               Zero or more serial device specifications of the form '<device>:<baudrate>:<port>' (<baudrate> and <port>
                        are optional

optional arguments:
  -h, --help            show this help message and exit
  -l, --listports       List available serial ports
  -I IPADDR, --ipaddr IPADDR
                        Server IP address
  -P IPPORT, --ipport IPPORT
                        Base server IP port
  -p RPYC_PORT, --rpyc_port RPYC_PORT
                        RPyC server port
  -C CONFIG, --config CONFIG
                        File containing descriptions of known devices

Source code

TCP to Serial Bridge source code