COSMOS Bridges provide an easy solution for getting data from devices that don’t speak Ethernet into COSMOS. Serial ports are the most common, but other devices such as USB, PCI cards, and Bluetooth devices can also be supported by using bridges to convert from a host computer accessible device, into an Ethernet byte stream that COSMOS can process from inside of containers.

Bridges are Meant to be Dumb

The purpose of bridges is to get bytes into COSMOS. Processing should be done in COSMOS itself, including details such as packet delineation.

Bridges are Generally Just an Interface and Router

Bridges are generally made up of a COSMOS Interface class that pull data from a host connected device, and a Router that forwards that data to COSMOS over TCP/IP. In most cases, data can be safely sent to COSMOS using the BURST protocol, and let the COSMOS side use the correct packet delineation protocol like LENGTH.

Host Requirements for Running Bridges

  • Requires a host Ruby installation (Ruby 3)
  • Install the OpenC3 gem
    • gem install openc3
  • Make sure the Ruby gem executable path is in your PATH environment variable
    • You can find this path by running gem environment and looking for EXECUTABLE DIRECTORY
  • If successful, you should be able to run openc3cli from a terminal

Bridge Configuration: bridge.txt

Bridges are run using an configuration file named bridge.txt. This file is a subset of the plugin.txt configuration syntax supporting VARIABLE, INTERFACE, ROUTER, and associated modifier keywords. However, BRIDGES HAVE NO KNOWLEDGE OF TARGETS. So instead of MAP_TARGETS, the INTERFACE is associated with the ROUTER using the ROUTE keyword.

The following is the default bridge.txt that is generated by running openc3cli bridgesetup

# Write serial port name
VARIABLE write_port_name COM1

# Read serial port name
VARIABLE read_port_name COM1

# Baud Rate
VARIABLE baud_rate 115200

# Parity - NONE, ODD, or EVEN

# Stop bits - 0, 1, or 2
VARIABLE stop_bits 1

# Write Timeout
VARIABLE write_timeout 10.0

# Read Timeout
VARIABLE read_timeout nil

# Flow Control - NONE, or RTSCTS
VARIABLE flow_control NONE

# Data bits per word - Typically 8
VARIABLE data_bits 8

# Port to listen for connections from COSMOS - Plugin must match
VARIABLE router_port 2950

# Port to listen on for connections from COSMOS. Defaults to localhost for security. Will need to be opened
# if COSMOS is on another machine.
VARIABLE router_listen_address

INTERFACE SERIAL_INT serial_interface.rb <%= write_port_name %> <%= read_port_name %> <%= baud_rate %> <%= parity %> <%= stop_bits %> <%= write_timeout %> <%= read_timeout %>
  OPTION FLOW_CONTROL <%= flow_control %>
  OPTION DATA_BITS <%= data_bits %>

ROUTER SERIAL_ROUTER tcpip_server_interface.rb <%= router_port %> <%= router_port %> 10.0 nil BURST
  OPTION LISTEN_ADDRESS <%= router_listen_address %>

VARIABLE provides default values to variables that can be changed when the bridge is started. This example shows an INTERFACE that is configured to use the serial_interface.rb class. It also includes a standard ROUTER using tcpip_server_interface.rb that COSMOS can connect to and get the data from the serial port. The LISTEN_ADDRESS is set to in this example to prevent access from outside of the host system. Docker running on the same machine can access this server using the host.docker.internal hostname and the configured port (2950 in this example).

Bridge Commands: openc3cli

openc3cli bridgesetup

Generates a bridge.txt example file

openc3cli bridge [filename] [variable1=value1] [variable2=value2]

Runs a bridge from a given configuration file. Defaults to bridge.txt in the current directory. Variables can also be passed into to override VARIABLE defaults.

openc3cli bridgegem [gem_name] [variable1=value1] [variable2=value2]

Runs a bridge using the bridge.txt provided in a bridge gem. Variables can also be passed into to override VARIABLE defaults.

Example Bridge Gems

Note on Serial Ports

Serial ports can be used directly without bridges on Linux Docker installations.

Add the following to the operator service in compose.yaml:

     - "/dev/ttyUSB0:/dev/ttyUSB0"

Make sure the serial device has permissions for the user running Docker to access:

sudo chmod 666 /dev/ttyUSB0