Skip to content
Branch: master
Find file History
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.

Building and Customizing your own Nav Server

We want to have a Nav Server:

  • Able to read from different sources (NMEA Serial port, TCP, whatever)
  • Able to compute data
  • Able to send or broadcast data on several channels
  • Able to run even if no WiFi network is available
  • Able to provide a Web Graphical User Interface, accessing server side REST Services

The NMEA.multiplexer is able to read, compute, and broadcast data, also accessible from a REST client.

To work even if no WiFi network is available, the best is probably to have the Raspberry Pi emit its own. This is totally feasible, follow the instructions provided here.

Now, depending on the configuration you want, several different components, from several different modules in this project will be required or not.

We will show here how to compose a custom server, based on your own needs.

The HTTP/REST server we use here is the one you find in the common-utils module. To minimize the footprint of the final application, all the static pages required by the web interface will be served from a single archive, as this feature is available from the HTTP Server we use here.

Note: The operations on a Serial Port would require libRxTx, and this dependency cannot be taken care of by Gradle. To be able to use it outside gradle, run (on Linux/Debian/Raspberry Pi), you need to install this package:

 sudo apt-get install librxtx-java

Another note: We want to footprint of all this to be as minimal sa possible. We will not have to clone the git repo on the destination machine, many of its components might not be required.

Close to "production"

It will not require the git repository to be cloned on the machine the server runs on.

We will:

  • Clone the repository on one machine, used to build the required components
  • Archive all the needed artifacts in a single archive (a tar.gz here), which can then be distributed
  • Transfer it to the final destination machine, where the archive will be expanded (aka un-archived)
  • Possibly modify some files
    • the /etc/rc.local for the server to start when the machine boots
    • the properties file that contains all the server's runtime parameters and definitions

Several of those steps can be scripted or automated, as you would see in the examples provided here. This basically all you need to get up and running.

We provide here several sub-directories, from which you will be able to run some provided scripts building several flavors of Nav Server flavors.

They all come with at least 3 files:

  •, the one you run, that will trigger all the required others
  • build.gradle, the Gradle script used for the build process, probably the most important here
  •, eventually triggered by, which will take care of building your application and archiving the produced artifacts.

Assuming that you've found (or defined for yourself) the configuration of your dreams, all you will need to do is:

  • From the Raspberry Pi used for the build, where you've clone the git repository: cd full.server (where full.server is your dream directory)
  • ./
    • During this step, you will have provided - from the command line - the name of the archive to produce, let's call it NMEADist as an example.
  • Now transfer the generated archive to the destination Raspberry Pi:
    • scp NMEADist.tar.gz pi@destination.pi:~
    • ssh pi@destination.pi
    • tar -xzvf NMEADist.tar.gz
    • cd NMEADist
    • ./

That's it, your server is up and running! (you might have modified the properties file, like, though. See the technical manual for details)

Now, from any browser on any machine connected on the server (Raspberry Pi)'s network, you can reach http://destination.pi:[port]/zip/index.html.

In the URL above, destination.pi is the name (or IP address) of the machine the server runs on, and [port] is the one defined in the mux's properties file, like in


This properties file is yours to tweak as needed.

To summarize, you went through the following steps:

  • build
  • archive
  • transfer
  • un-archive
  • run

Pick and choose your features in other modules, grab the web ages you need, modify the index.html, etc, and run the script to package everything for distribution.

The "pick and choose" part could be scripted as well, as seen in the provided examples.

This project is not supposed to contain any source file except web resources (archived).

It pulls the NMEA.multiplexer, RESTNavServer, and the NMEA.mux.extensions projects (or whatever you want or need). This is what you would tweak to fit your requirements.

When available, the file rc.local is to give you some inspiration, so you can modify the one in /etc/rc.local on the destination machine to start the Multiplexer at boot time.

The script (available in each directory) is not carved in stone. It is also here for inspiration.

Note: To make sure the runtime components will be 100% compatible with your Raspberry Pi target, I use to run this build on a Raspberry Pi (not on a Windows or Mac laptop, carefull with Linux, probably OK with a Raspberry Pi Desktop). The (only) problem that can potentially show up is a Java version mismatch. The build process might be a bit too heavy for a Raspberry Pi Zero... I usually build on a bigger board (A, or B), and then scp the result to a Raspberry Pi Zero if that is the one I want to run my server on, as shown above with the scp command.


This project directory is a play ground, again, it is here for you to compose your own server.


Means not me. 🤓

Examples (for inspiration)

Note: The Raspberry Pi (pretty much all models) can host the navigation server, along with its REST/HTTP companion, without problem. One possibly challenging thing though, would be to run the Web GUI on the Graphical Desktop. This turns out to be quite demanding, and this requires a more beefy Raspberry Pi. As usual, and as everywhere, a GUI is something very demanding.

The examples list contains

  • Full Navigation Server
    • Read Serial port (NMEA, GPS), log, display on small screen, TCP rebroadcast, Web Interface, Celestial Computer, Tide Computer, etc
  • Minimal Navigation server
    • Read a GPS (or NMEA Station), and log data into a file. Suitable for running, kayaking, and such small configurations.
  • Extended Navigation Server
    • Based on the Full Navigation Server above, shows how to add 2 push-buttons to the configuration, for the user to interact with the software.
  • Extended Navigation Server, #2
    • Based on the Full Navigation Server above, shows how to add 2 push-buttons to the configuration, for the user to interact with the software, including shutting down the machine. Also has a GPS on a bonnet.
  • Embarked Head Up display
    • Uses the Graphical Desktop to display a Web Interface in a browser. More demanding than the others, requires a more powerful config (Raspberry Pi 3B+).

Full Nav Server

All features: NMEA multiplexer, Web Interface, Celestial Computer, Tides, Almanacs publication, Weather Wizard, Small screens, ...

Full Server

 $ cd full.server
 $ ./

Small SSD1306 Oled Screen

Small Nokia cellphone Screen

Minimal Multiplexer

 $ cd minimal.mux
 $ ./

See in the how web resources are copied, and from where. Then look into how it launches a Gradle build, and in the corresponding build.gradle that it only depends on NMEA.multiplexer.

TODO Screenshots of the settings (hardware).

Full Nav Server, extended

all features: NMEA multiplexer, Celestial Computer, Tides, Almanacs publication, Weather Wizard, Small screens, ...

The idea here is to show how to extend the classes provided in the project to implement your own extra features.

 $ cd full.server.extended
 $ ./

Small Nav Server, extended

all features: NMEA multiplexer, Celestial Computer, Tides, Almanacs publication, Weather Wizard, Small screens, ... Push buttons for interaction with the software, embedded GPS, LiPo battery.


With a 5" or 7" TFT screen

 $ cd head.up
 $ ./

Or in details:

  • Use switch2tftscreen (at the root of the project)
  • Reboot

You can boot directly to the Graphical Desktop (sudo raspi-config), and automatically start a browser on a given URL as soon as the Desktop is up and running.

To do that, you need to have Chromium installed, and boot to the Graphical Desktop.

To start Chromium when the Desktop starts, and load one or several URLs (in different tabs), edit the file named ~/.config/lxsession/LXDE-pi/autostart, and add, at the end, the following lines:

@chromium-browser --incognito --kiosk [--force-device-scale-factor=0.90] http://localhost:9999/web/nmea/headup.html \
                                      [url.2] \
                                      [url.3] \

It will start Chromium in kiosk (aka full screen) mode, and load the URLs mentioned above.

Also important here

A Graphical Desktop will by default go to sleep if not solicited for a while, and we do not want that. To fix it:

  • Edit /etc/lightdm/lightdm.conf
  • Have a/the line that starts with xserver-command= to look like xserver-command=X -s 0 -dpms

This will take effect after reboot.

With a small USB GPS like U-blox 7

The U-blox 7 is a small and cheap GPS you can plug with a USB socket. And it works.

$ lsusb
Bus 001 Device 006: ID 1546:01a7 U-Blox AG 
$ dmesg | grep -i gps
[  646.871190] usb 1-1.3: Product: u-blox 7 - GPS/GNSS Receiver

Seems to mount on /dev/ttyACM0

Note: In case you have problem reading /dev/ttyACM0, create a symbolic link

$ sudo ln -s /dev/ttyACM0 /dev/ttyS80

Then try reading or writing on /dev/ttyS80

To unlink:

$ sudo unlink /dev/ttyS80

To check the device, run the script in the Serial.IO module, after modifying the parameters (USB port)

$ ./
Make sure the GPS is connected it through its USB cable.
Assuming Linux/Raspberry Pi
Executing sudo java -Dserial.port=/dev/ttyS80 -Dbaud.rate=4800 -Djava.library.path=/usr/lib/jni -cp ./build/libs/Serial.IO-1.0-all.jar:/usr/share/java/RXTXcomm.jar sample.GPSReader ...
Enter [Return]

Stable Library
Native lib Version = RXTX-2.2pre2
Java lib Version   = RXTX-2.1-7
WARNING:  RXTX Version mismatch
	Jar version = RXTX-2.1-7
	native lib Version = RXTX-2.2pre2
RXTX Warning:  Removing stale lock file. /var/lock/LCK..ttyS80
== Serial Port List ==
-> /dev/ttyS80
Opening port /dev/ttyS80:4800
GPS connected: true
IO Streams initialized
$GPTXT,01,01,02,u-blox ag -*50
$GPTXT,01,01,02,HW  UBX-G70xx   00070000 FF7FFFFFo*69
$GPTXT,01,01,02,ROM CORE 1.00 (59842) Jun 27 2012 17:43:52*59
$GPTXT,01,01,02,PROTVER 14.00*1E

Start ./ or its equivalent, choose option 4.

To automate all this, for the web page to be displayed when the server (Raspberry Pi) boots:

  • Using raspi-config, choose to boot to the Graphical Desktop
  • in /etc/rc.local, start the Navigation Server with the appropriate properties file
echo "-- From /etc/rc.local --"
echo "Now starting NMEA Multiplexer"
cd ~pi/raspberry-coffee/RESTNavServer/launchers
# Wait...
sleep 20
nohup ./ --no-date &
cd -
  • Make sure the file ~/.config/lxsession/LXDE-pi/autostart is modified to open Chromium on the right page.
  • Make sure you've disabled the screen sleep as described above

Note: This config does not need any network, it runs in standalone, but nothing is preventing any network operation. You can can add one (hotspot or not) if needed.

From a browser, reach http://localhost:9999/web/nmea/headup.html. The mirror and star-wars effect is all done in CSS.

Head Up!

Click the pictures to see them bigger.

Setting Direct Position
Setting Position
Direct Heading Direct Speed
Heading Speed
Reflected Position Reflected Heading
Real Position Real Heading
Reflected Speed In the car
Speed In the car
Speed In the car

You can see the data displayed on the windshield and still look through it.

Distortion of the reflected screen can be controlled in the CSS Stylesheet, by adjusting the variables perspective, rotateX and scale-y-factor.

	:root {
		--perspective: 50em;
		--rotateX: -50deg;
		--scale-y-factor: 1.5;

In the car, with an OBD (On Board Diagnostic) interface (usually using Bluetooth), we could display all kind of data. This will be another project.

Note: Try on a Raspberry Pi 3B+, the client part (running in the browser) is a bit demanding...

For logged data

See in the NMEA.multiplexer project


In the NMEA.mux.WebUI project, logged folder


TODO REST clients in other projects

... More to come (coming)

  • With SSD1306 32x128
  • With SSD1306 64x128. Done
  • With Nokia5110. Done
  • With UART GPS
  • Push Buttons and Switches. Done

For the logger:

  • 2 Bonnets:
    • One for the GPS (Adafruit Ultimate GPS)
    • Another on top, with a HAT (Hardware Attached on Top) like this:


See here for the wiring diagrams.

You can’t perform that action at this time.