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.
Navproc Container
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.