Skip to content

Development

Developer Environment

This page documents a local development environment that can be used to work on this software stack. The idea is to build a docker system that contains all components of the production system so that we can develop with confidence. The high level diagram of the system is shown below

--- title: Developer Environment --- flowchart LR subgraph host-machine subgraph docker direction LR subgraph sim-sources direction LR subgraph source-processes direction LR nmea-gps-simulator end subgraph source-serial-ports direction LR source-port1["/dev/ttyr00"] source-port2["/dev/ttyr01"] source-port3["/dev/ttyr02"] source-port4["/dev/ttyr03"] source-port5["/dev/ttyr04"] source-port6["/dev/ttyr05"] source-port7["/dev/ttyr06"] source-port8["/dev/ttyr07"] source-port9["/dev/ttyr08"] source-port10["/dev/ttyr09"] source-port11["/dev/ttyr0a"] source-port12["/dev/ttyr0b"] source-port13["/dev/ttyr0c"] source-port14["/dev/ttyr0d"] source-port15["/dev/ttyr0e"] source-port16["/dev/ttyr0f"] end subgraph source-ip-ports direction LR source-ip-port1[12301] source-ip-port2[12302] source-ip-port3[12303] source-ip-port4[12304] source-ip-port5[12305] source-ip-port6[12306] source-ip-port7[12307] source-ip-port8[12308] source-ip-port9[12309] source-ip-port10[12310] source-ip-port11[12311] source-ip-port12[12312] source-ip-port13[12313] source-ip-port14[12314] source-ip-port15[12315] source-ip-port16[12316] end end subgraph navproc direction LR subgraph navproc-ip-ports direction LR navproc-ip-port1 navproc-ip-port2 navproc-ip-port3 navproc-ip-port4 navproc-ip-port5 navproc-ip-port6 navproc-ip-port7 navproc-ip-port8 navproc-ip-port9 navproc-ip-port10 navproc-ip-port11 navproc-ip-port12 navproc-ip-port13 navproc-ip-port14 navproc-ip-port15 navproc-ip-port16 end subgraph navproc-serial-ports direction LR navproc-port1["/dev/ttya00"] navproc-port2["/dev/ttya01"] navproc-port3["/dev/ttya02"] navproc-port4["/dev/ttya03"] navproc-port5["/dev/ttya04"] navproc-port6["/dev/ttya05"] navproc-port7["/dev/ttya06"] navproc-port8["/dev/ttya07"] navproc-port9["/dev/ttya08"] navproc-port10["/dev/ttya09"] navproc-port11["/dev/ttya10"] navproc-port12["/dev/ttya11"] navproc-port13["/dev/ttya12"] navproc-port14["/dev/ttya13"] navproc-port15["/dev/ttya14"] navproc-port16["/dev/ttya15"] end subgraph navproc-processes direction LR nmea-gps-serin --> nmea-gps end subgraph lcm-channels nmea-gps-serin-channel[NMEA_GPS_SERIN] nmea-gps[NMEA_GPS] end subgraph logger-processes direction LR shipnavlogr end subgraph lcm-bridge direction LR end end subgraph api direction LR zmq redis udp-proxy influxdb grafana end end end

Signal Generator Container

flowchart LR subgraph signal-generator-container direction LR subgraph source-serial-ports source-port1["/dev/ttyr00"] source-port2["/dev/ttyr01"] source-port3["/dev/ttyr02"] source-port4["/dev/ttyr03"] source-port5["/dev/ttyr04"] source-port6["/dev/ttyr05"] source-port7["/dev/ttyr06"] source-port8["/dev/ttyr07"] source-port9["/dev/ttyr08"] source-port10["/dev/ttyr09"] source-port11["/dev/ttyr0a"] source-port12["/dev/ttyr0b"] source-port13["/dev/ttyr0c"] source-port14["/dev/ttyr0d"] source-port15["/dev/ttyr0e"] source-port16["/dev/ttyr0f"] end subgraph source-ip-ports source-ip-port1[12300] source-ip-port2[12301] source-ip-port3[12302] source-ip-port4[12303] source-ip-port5[12304] source-ip-port6[12305] source-ip-port7[12306] source-ip-port8[12307] source-ip-port9[12308] source-ip-port10[12309] source-ip-port11[12310] source-ip-port12[12311] source-ip-port13[12312] source-ip-port14[12313] source-ip-port15[12314] source-ip-port16[12315] end end source-port1 --> source-ip-port1 source-port2 --> source-ip-port2 source-port3 --> source-ip-port3 source-port4 --> source-ip-port4 source-port5 --> source-ip-port5 source-port6 --> source-ip-port6 source-port7 --> source-ip-port7 source-port8 --> source-ip-port8 source-port9 --> source-ip-port9 source-port10 --> source-ip-port10 source-port11 --> source-ip-port11 source-port12 --> source-ip-port12 source-port13 --> source-ip-port13 source-port14 --> source-ip-port14 source-port15 --> source-ip-port15 source-port16 --> source-ip-port16

This is a docker container that is an Ubuntu 24.04 base image. We first install socat so that we can emulate the serial ports. Next, we use a script and supervisord to create the virtual serial ports at startup. The script to create the ports looks like this:

#!/bin/bash

# Create 16 virtual serial ports using socat
socat -d -d pty,raw,echo=0,link=/dev/ttyr00 tcp-listen:12300 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr01 tcp-listen:12301 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr02 tcp-listen:12302 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr03 tcp-listen:12303 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr04 tcp-listen:12304 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr05 tcp-listen:12305 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr06 tcp-listen:12306 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr07 tcp-listen:12307 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr08 tcp-listen:12308 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr09 tcp-listen:12309 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr0a tcp-listen:12310 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr0b tcp-listen:12311 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr0c tcp-listen:12312 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr0d tcp-listen:12313 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr0e tcp-listen:12314 &
socat -d -d pty,raw,echo=0,link=/dev/ttyr0f tcp-listen:12315 &

wait

I used the ttyr designator so it matches the Moxa on the real system. Once this container is up and running, there are 16 virtual serial ports running that are then linked to their respective IP ports which is where the other container will connect to.

flowchart LR subgraph host-docker direction LR subgraph signal-generator-container source-ip-port1[12300] source-ip-port2[12301] source-ip-port3[12302] source-ip-port4[12303] source-ip-port5[12304] source-ip-port6[12305] source-ip-port7[12306] source-ip-port8[12307] source-ip-port9[12308] source-ip-port10[12309] source-ip-port11[12310] source-ip-port12[12311] source-ip-port13[12312] source-ip-port14[12313] source-ip-port15[12314] source-ip-port16[12315] end subgraph navproc-container navproc-port1["/dev/ttya00"] navproc-port2["/dev/ttya01"] navproc-port3["/dev/ttya02"] navproc-port4["/dev/ttya03"] navproc-port5["/dev/ttya04"] navproc-port6["/dev/ttya05"] navproc-port7["/dev/ttya06"] navproc-port8["/dev/ttya07"] navproc-port9["/dev/ttya08"] navproc-port10["/dev/ttya09"] navproc-port11["/dev/ttya10"] navproc-port12["/dev/ttya11"] navproc-port13["/dev/ttya12"] navproc-port14["/dev/ttya13"] navproc-port15["/dev/ttya14"] navproc-port16["/dev/ttya15"] end end source-ip-port1 --> navproc-port1 source-ip-port2 --> navproc-port2 source-ip-port3 --> navproc-port3 source-ip-port4 --> navproc-port4 source-ip-port5 --> navproc-port5 source-ip-port6 --> navproc-port6 source-ip-port7 --> navproc-port7 source-ip-port8 --> navproc-port8 source-ip-port9 --> navproc-port9 source-ip-port10 --> navproc-port10 source-ip-port11 --> navproc-port11 source-ip-port12 --> navproc-port12 source-ip-port13 --> navproc-port13 source-ip-port14 --> navproc-port14 source-ip-port15 --> navproc-port15 source-ip-port16 --> navproc-port16

This is a docker container that is an Ubuntu 22.04 base image. We first install socat so that we can emulate the serial ports. Next, we use a script and supervisord to create the virtual serial ports at startup. The script to create the ports looks like this:

#!/bin/bash

# Create 16 virtual serial ports using socat
socat -d -d pty,raw,echo=0,link=/dev/ttya00 tcp-connect:192.168.1.10:12300 &
socat -d -d pty,raw,echo=0,link=/dev/ttya01 tcp-connect:192.168.1.10:12301 &
socat -d -d pty,raw,echo=0,link=/dev/ttya02 tcp-connect:192.168.1.10:12302 &
socat -d -d pty,raw,echo=0,link=/dev/ttya03 tcp-connect:192.168.1.10:12303 &
socat -d -d pty,raw,echo=0,link=/dev/ttya04 tcp-connect:192.168.1.10:12304 &
socat -d -d pty,raw,echo=0,link=/dev/ttya05 tcp-connect:192.168.1.10:12305 &
socat -d -d pty,raw,echo=0,link=/dev/ttya06 tcp-connect:192.168.1.10:12306 &
socat -d -d pty,raw,echo=0,link=/dev/ttya07 tcp-connect:192.168.1.10:12307 &
socat -d -d pty,raw,echo=0,link=/dev/ttya08 tcp-connect:192.168.1.10:12308 &
socat -d -d pty,raw,echo=0,link=/dev/ttya09 tcp-connect:192.168.1.10:12309 &
socat -d -d pty,raw,echo=0,link=/dev/ttya10 tcp-connect:192.168.1.10:12310 &
socat -d -d pty,raw,echo=0,link=/dev/ttya11 tcp-connect:192.168.1.10:12311 &
socat -d -d pty,raw,echo=0,link=/dev/ttya12 tcp-connect:192.168.1.10:12312 &
socat -d -d pty,raw,echo=0,link=/dev/ttya13 tcp-connect:192.168.1.10:12313 &
socat -d -d pty,raw,echo=0,link=/dev/ttya14 tcp-connect:192.168.1.10:12314 &
socat -d -d pty,raw,echo=0,link=/dev/ttya15 tcp-connect:192.168.1.10:12315 &

wait

I used the ttyr designator so it matches the Moxa on the real system. Once this container is up and running, there are 16 virtual serial ports running that are then linked to their respective IP ports which is where the other container will connect to.