A lightweight, cross-platform NTRIP client for Linux, macOS, and Windows that:
- Connects to an NTRIP caster to receive RTCM correction data
- Reads GGA NMEA messages from a GPS receiver on a serial port
- Sends GGA position to the NTRIP caster for VRS (Virtual Reference Station) support
- Forwards RTCM corrections to the GPS receiver
- Runs a TCP server to forward serial data to multiple clients
# Using make make # Or directly with g++ g++ -std=c++17 -O2 -o ntrip_client ntrip_client.cpp -pthread
Using Visual Studio Developer Command Prompt:
cl /EHsc /std:c++17 /O2 ntrip_client.cpp ws2_32.lib
Using MinGW-w64:
g++ -std=c++17 -O2 -o ntrip_client.exe ntrip_client.cpp -lws2_32
Create a config.json file:
{
"ntrip_host": "truertk.pointonenav.com",
"ntrip_port": 2101,
"ntrip_mountpoint": "POLARIS",
"ntrip_user": "your_username",
"ntrip_password": "your_password",
"serial_port": "/dev/ttyUSB0",
"serial_baud": 115200,
"tcp_port": 5000,
"gga_interval_sec": 10
}Note: On Windows, use "serial_port": "COM3" (or appropriate COM port).
| Field | Required | Default | Description |
|---|---|---|---|
ntrip_host |
Yes | - | NTRIP caster hostname |
ntrip_port |
No | 2101 | NTRIP caster port |
ntrip_mountpoint |
Yes | - | Mountpoint name |
ntrip_user |
No | - | Username for authentication |
ntrip_password |
No | - | Password for authentication |
serial_port |
Yes | - | Serial port path (e.g., /dev/ttyUSB0, COM3) |
serial_baud |
No | 9600 | Baud rate (4800, 9600, 19200, 38400, 57600, 115200, 230400) |
tcp_port |
No | 0 | TCP server port for forwarding serial data (0 = disabled) |
gga_interval_sec |
No | 10 | Interval for sending GGA to caster |
When tcp_port is set, the client starts a TCP server that forwards all serial data to connected clients. Multiple clients can connect simultaneously.
Example: Connect with netcat
nc localhost 5000
Example: Connect with Python
There is a full featured example in the python folder which connects to the TCP port and generates a live webpage with position and signal strength.
python python/gps_plotter.py
./ntrip_client config.json
Press Ctrl+C to stop.
On Linux, you may need to add your user to the dialout group:
sudo usermod -a -G dialout $USER # Log out and back in for changes to take effect
On macOS, serial ports are typically accessible without additional configuration.
Linux:
- USB serial:
/dev/ttyUSB0,/dev/ttyUSB1 - ACM devices:
/dev/ttyACM0,/dev/ttyACM1
macOS:
- USB serial:
/dev/tty.usbserial-*,/dev/tty.usbmodem*
Windows:
- COM ports:
COM1,COM3,COM10, etc.
List available ports:
# Linux ls /dev/tty* # macOS ls /dev/tty.* # Windows (PowerShell) [System.IO.Ports.SerialPort]::GetPortNames() # Windows (Command Prompt) mode
- Opens the serial port and connects to the GPS receiver
- Connects to the NTRIP caster and authenticates
- Reads NMEA data from the serial port, parsing GGA messages
- Sends GGA messages to the NTRIP caster periodically (for VRS)
- Receives RTCM correction data from the caster
- Writes RTCM data to the serial port (to the GPS receiver)
- Optionally forwards all serial data to a TCP socket
None! Uses only standard C++17 and platform APIs:
- Linux/macOS: POSIX (termios, sockets)
- Windows: Win32 API (serial), Winsock2 (sockets)
The project includes a comprehensive test suite with unit tests and integration tests.
# Run all tests make test # Run only unit tests make test-unit # Run only integration tests make test-integration # Run integration test with custom duration (default 15 seconds) cd test && ./run_tests.sh integration 30
The test suite includes:
-
Unit Tests
- GGA message extraction
- Base64 encoding for authentication
- JSON configuration parsing
-
Integration Test
- Mock NTRIP server that validates connections and receives GGA
- GPS simulator that generates NMEA sentences on a PTY
- Full end-to-end data flow verification
You can also run the test components manually:
# Build test binaries make test-binaries # Terminal 1: Start mock NTRIP server ./build/mock_ntrip_server -p 2101 -m TEST -u user -P pass # Terminal 2: Start GPS simulator (note the PTY path it prints) ./build/gps_simulator # Terminal 3: Create test config and run client # (use PTY path from GPS simulator output as serial_port) ./ntrip_client test_config.json
The systemd/ directory contains everything needed to run the NTRIP client as a system service on Linux.
# Build the client make # Install the service (uses config.json from current directory) sudo ./systemd/install-service.sh # Or specify a custom config file sudo ./systemd/install-service.sh /path/to/my-config.json
-
Create a dedicated user:
sudo useradd -r -s /usr/sbin/nologin -G dialout ntrip
-
Install the binary:
sudo cp ntrip_client /usr/local/bin/ sudo chmod 755 /usr/local/bin/ntrip_client
-
Install the configuration:
sudo mkdir -p /etc/ntrip sudo cp config.json /etc/ntrip/ sudo chmod 640 /etc/ntrip/config.json sudo chown root:ntrip /etc/ntrip/config.json
-
Install the service file:
sudo cp systemd/ntrip-client.service /etc/systemd/system/ sudo systemctl daemon-reload
-
Enable and start the service:
sudo systemctl enable ntrip-client sudo systemctl start ntrip-client
# Check service status sudo systemctl status ntrip-client # View logs (live) sudo journalctl -u ntrip-client -f # View recent logs sudo journalctl -u ntrip-client --since "1 hour ago" # Restart after config change sudo systemctl restart ntrip-client # Stop the service sudo systemctl stop ntrip-client # Disable auto-start sudo systemctl disable ntrip-client
When running as a service, the configuration file is located at:
/etc/ntrip/config.json
Edit it with:
sudo nano /etc/ntrip/config.json sudo systemctl restart ntrip-client
The service runs as the ntrip user which is added to the dialout group. This provides access to serial ports. If you're using a USB-serial adapter, make sure it appears as /dev/ttyUSB* or /dev/ttyACM*.
If your device uses a different path, edit the service file:
sudo systemctl edit ntrip-client
Add:
[Service] DeviceAllow=/dev/your-device rw
Service won't start:
# Check for errors sudo journalctl -u ntrip-client -e # Test config manually sudo -u ntrip /usr/local/bin/ntrip_client /etc/ntrip/config.json
Permission denied on serial port:
# Check device permissions ls -la /dev/ttyUSB0 # Verify ntrip user is in dialout group groups ntrip # Add to dialout group if needed sudo usermod -a -G dialout ntrip sudo systemctl restart ntrip-client
Service keeps restarting:
- Check logs for connection errors
- Verify NTRIP server credentials
- Check network connectivity
sudo ./systemd/uninstall-service.sh
Or manually:
sudo systemctl stop ntrip-client sudo systemctl disable ntrip-client sudo rm /etc/systemd/system/ntrip-client.service sudo systemctl daemon-reload sudo rm /usr/local/bin/ntrip_client sudo rm -rf /etc/ntrip sudo userdel ntrip
MIT License - feel free to use and modify.