NTRIP Caster API Documentation

Developer reference for connecting base stations and rover clients to PrairieRTK.

Contents

Overview

PrairieRTK operates an NTRIP (Networked Transport of RTCM via Internet Protocol) caster that distributes centimeter-level GNSS correction data across Alberta's base station network. The caster runs as a TCP server on port 2101 and supports up to 200 concurrent connections.

The system provides both single-base corrections (raw RTCM3 from physical stations) and Virtual Reference Station (VRS) corrections interpolated from the full network to your rover's exact position.

Endpoint: Connect your GNSS receiver or NTRIP client to prairiertk.polsia.app:2101

Protocol Support

PrairieRTK supports both NTRIP v1 and NTRIP v2 request formats.

FeatureNTRIP v1NTRIP v2
Source table request GET / HTTP/1.0 GET / HTTP/1.1
Rover (client) request GET /MOUNT HTTP/1.0 GET /MOUNT HTTP/1.1 or
POST /MOUNT HTTP/1.1
Base station (source) SOURCE password /MOUNT
Authentication HTTP Basic (Authorization: Basic <base64>)
GGA position Ntrip-GGA: header or NMEA in body
Success response (client) ICY 200 OK ICY 200 OK
Success response (source) HTTP/1.1 200 OK

Authentication

Rover clients authenticate via HTTP Basic Authentication. Encode your credentials as Base64(username:password) and include them in the Authorization header.

Request Format

GET /VRS_AB HTTP/1.1
Host: prairiertk.polsia.app
Authorization: Basic cm92ZXI6cnRrX3JvdmVy
Ntrip-Version: Ntrip/2.0
Ntrip-GGA: $GPGGA,142305.00,...*XX

Auth Modes

ModeBehavior
Authenticated Users defined in config/users.json — credentials required. Invalid credentials return 401 Unauthorized.
Open access If no users file exists or is empty, all connections are accepted without credentials.

Error Responses

HTTP StatusMeaning
401 UnauthorizedMissing or invalid credentials
404 Not FoundMountpoint does not exist
503 Service UnavailableServer at max connection capacity
400 Bad RequestUnrecognized request format

Source Table

Request the source table to discover available mountpoints. Send a GET / request (no mountpoint path) to the caster.

Request

# NTRIP v1
GET / HTTP/1.0
User-Agent: NTRIP MyClient/1.0

# NTRIP v2
GET / HTTP/1.1
Host: prairiertk.polsia.app
Ntrip-Version: Ntrip/2.0

Response

SOURCETABLE 200 OK
Content-Type: text/plain
Server: PrairieRTK-NTRIP/1.0
Content-Length: 432

STR;EDMO_RTCM3;Edmonton;RTCM 3.3;;2;GPS+GLO;PrairieRTK;CAN;53.5461;-113.4938;0;0;PrairieRTK;none;B;N;0;
STR;CALG_RTCM3;Calgary;RTCM 3.3;;2;GPS+GLO;PrairieRTK;CAN;51.0447;-114.0719;0;0;PrairieRTK;none;B;N;0;
STR;VRS_AB;VRS_AB;RTCM 3.3;;2;GPS+GLO;PrairieRTK;CAN;52.0000;-113.5000;0;0;PrairieRTK;none;B;N;0;
ENDSOURCETABLE

STR Record Fields

PositionFieldExampleDescription
1TypeSTRAlways "STR" for stream records
2MountpointEDMO_RTCM3Name used in GET request path
3IdentifierEdmontonHuman-readable city/location
4FormatRTCM 3.3Data format
6Carrier20=None, 1=L1, 2=L1+L2
7Nav SystemGPS+GLOSatellite constellations
8NetworkPrairieRTKNetwork operator
9CountryCANISO 3166 code
10Latitude53.5461Station latitude (degrees)
11Longitude-113.4938Station longitude (degrees)
16AuthBB=Basic, N=None, D=Digest
17FeeNN=No fee, Y=Fee required

Mountpoints

PrairieRTK provides two types of mountpoints:

Physical Station Mountpoints

Direct RTCM3 streams from individual base stations. Each station broadcasts GPS and GLONASS observations. Best when your rover is within ~30 km of the station.

MountpointStationLatitudeLongitudeHeight (m)
EDMO_RTCM3Edmonton53.5461-113.4938668.0
CALG_RTCM3Calgary51.0447-114.07191045.0
RDDR_RTCM3Red Deer52.2681-113.8112847.0
LETH_RTCM3Lethbridge49.6942-112.8328920.0
GRDP_RTCM3Grande Prairie55.1707-118.7946669.0

VRS Mountpoint

MountpointTypeDescription
VRS_AB Virtual Reference Station Network-interpolated corrections computed for your rover's exact position. Requires GGA sentence in the initial request. Works anywhere within the station network.
Recommendation: Use VRS_AB for best accuracy across Alberta. The VRS engine interpolates ionospheric, tropospheric, and geometric corrections from the 3 nearest base stations using inverse distance weighting (IDW).

Rover Client Connection

To receive RTCM3 corrections as a rover client:

Step 1 — Connect via TCP

Open a TCP connection to the caster host on port 2101.

Step 2 — Send NTRIP Request

# v1 GET request
GET /VRS_AB HTTP/1.0
User-Agent: NTRIP MyRover/1.0
Authorization: Basic cm92ZXI6cnRrX3JvdmVy
Ntrip-GGA: $GPGGA,142305.00,5232.8086,N,11343.5180,W,4,12,0.8,857.0,M,0.0,M,,*5B

# v2 POST request (GGA in body)
POST /VRS_AB HTTP/1.1
Host: prairiertk.polsia.app
Ntrip-Version: Ntrip/2.0
Authorization: Basic cm92ZXI6cnRrX3JvdmVy

$GPGGA,142305.00,5232.8086,N,11343.5180,W,4,12,0.8,857.0,M,0.0,M,,*5B

Step 3 — Receive Corrections

On success, the caster responds with ICY 200 OK followed by a continuous binary RTCM3 stream. Each RTCM3 frame starts with the sync byte 0xD3, followed by a 10-bit length field, the message payload, and a 24-bit CRC.

Step 4 — Send Updated GGA (VRS)

When connected to a VRS mountpoint, periodically send updated GGA sentences as your rover moves. The caster re-computes corrections for the new position. Send the NMEA sentence as raw ASCII on the same TCP connection:

# Send updated position every 10-60 seconds
$GPGGA,142315.00,5232.8100,N,11343.5200,W,4,12,0.8,858.2,M,0.0,M,,*5A

The caster detects $GPGGA or $GNGGA prefixes and triggers new VRS corrections automatically.

Base Station Connection

To push RTCM3 observation data from a base station (NTRIP server/source), use the SOURCE command:

SOURCE <password> /<mountpoint>
Source-Agent: NTRIP MyBase/1.0

Example

SOURCE prairie2024 /EDMO_RTCM3
Source-Agent: NTRIP Trimble/5.0

On success, the caster responds with HTTP/1.1 200 OK. After that, send raw RTCM3 binary frames on the connection. The caster relays data to all subscribed rover clients on that mountpoint.

Important: The mountpoint must already be registered before a source can attach. Mountpoints are defined in the server configuration at startup.

GGA Sentence Integration

NMEA GGA (Global Positioning System Fix Data) sentences tell the VRS engine where your rover is located. This is essential for VRS mountpoints — the caster interpolates corrections specific to your position.

Supported GGA Talker IDs

GGA Field Format

$GPGGA,HHMMSS.ss,DDMM.MMMMM,N|S,DDDMM.MMMMM,E|W,Q,NN,H.H,AAA.A,M,GG.G,M,A.A,RRRR*CC

Field breakdown:
 1  HHMMSS.ss       UTC time
 2  DDMM.MMMMM     Latitude (degrees + minutes)
 3  N|S             North or South
 4  DDDMM.MMMMM    Longitude (degrees + minutes)
 5  E|W             East or West
 6  Q               Fix quality (1=GPS, 2=DGPS, 4=RTK fixed, 5=RTK float)
 7  NN              Number of satellites
 8  H.H             HDOP
 9  AAA.A           Altitude above MSL (meters)
10  M               Altitude units
11  GG.G            Geoid separation (meters)
12  M               Geoid units
13  A.A             Age of DGPS data
14  RRRR            Reference station ID
 *  CC              Checksum (XOR of chars between $ and *)

How to Include GGA

You can send your GGA position in two ways:

  1. Ntrip-GGA header — Include Ntrip-GGA: $GPGGA,... as an HTTP header in your initial connection request.
  2. In-band NMEA — After connection, send raw GGA sentences on the TCP stream. The caster detects lines starting with $GPGGA or $GNGGA and re-triggers VRS computation.
Tip: For VRS mountpoints, send an initial GGA in the request header and then update every 10–60 seconds as the rover moves. Most GNSS receivers do this automatically.

RTCM3 Message Types

PrairieRTK encodes and decodes the following RTCM3 message types:

MessageNameContentUsed For
1004 Extended L1/L2 GPS GPS pseudorange & carrier-phase on L1 + L2 Primary GPS corrections
1005 Station ARP Antenna Reference Point (ECEF X, Y, Z) Station/VRS position
1006 Station ARP + Height ECEF position + antenna height Station position with height
1012 Extended L1/L2 GLONASS GLONASS pseudorange & carrier-phase on L1 + L2 GLONASS corrections
1033 Receiver/Antenna Descriptor Equipment make, model, serial, firmware Station metadata
1077 GPS MSM7 Full GPS observations (all signals, high resolution) High-precision GPS
1087 GLONASS MSM7 Full GLONASS observations (all signals, high resolution) High-precision GLONASS

RTCM3 Frame Structure

┌──────────┬────────────┬──────────────┬──────────┐
│ Preamble │   Length   │   Payload    │  CRC-24Q │
│  0xD3    │  10 bits   │  N bytes     │  3 bytes │
│  1 byte  │  2 bytes   │  (variable)  │          │
└──────────┴────────────┴──────────────┴──────────┘

Total frame size = 3 (header) + N (payload) + 3 (CRC) = N + 6 bytes

VRS Corrections

The Virtual Reference Station engine creates a synthetic base station at your rover's location by interpolating observations from the surrounding physical network.

How It Works

  1. Rover sends its position via GGA sentence
  2. VRS engine identifies the 3+ nearest base stations (configurable via minStations)
  3. Ionospheric delays are interpolated using Inverse Distance Weighting (IDW)
  4. Tropospheric delays are computed via the Saastamoinen model
  5. Geometric corrections account for satellite angle differences between base and VRS
  6. Synthetic observations are encoded as RTCM3 messages (1005 + 1004 + 1012) and sent to the rover

VRS Output Messages

When you connect to VRS_AB, you receive:

MessagePurpose
1005VRS station position (ECEF) — set to your rover's location
1004GPS L1/L2 observations interpolated for your position
1012GLONASS L1/L2 observations interpolated for your position

Requirements

Configuration

The caster reads from config/config.json on startup:

{
  "caster": {
    "port": 2101,              // TCP listen port
    "maxConnections": 200      // Max simultaneous clients
  },
  "vrs": {
    "updateInterval": 1000,    // VRS refresh interval (ms)
    "minStations": 3,          // Minimum bases for VRS computation
    "idwPower": 2              // IDW interpolation exponent
  },
  "logging": {
    "level": "info",           // error | warn | info | debug
    "directory": "logs"
  },
  "auth": {
    "usersFile": "config/users.json"
  }
}

User Configuration

Define users in config/users.json:

{
  "users": [
    { "username": "rover1", "password": "secure_pass" },
    { "username": "survey", "password": "another_pass" }
  ]
}

Station Registry

Base stations are registered in config/stations.json:

{
  "stations": [
    {
      "id": "EDMO",
      "name": "Edmonton",
      "lat": 53.5461,
      "lon": -113.4938,
      "height": 668.0,
      "mountpoint": "EDMO_RTCM3",
      "expected_messages": [1004, 1012, 1077, 1087, 1005],
      "active": true
    }
  ]
}

Client Configuration Examples

RTKLIB (str2str)

# Connect to VRS mountpoint
str2str -in ntrip://rover:rtk_rover@prairiertk.polsia.app:2101/VRS_AB \
  -out serial://ttyUSB0:115200

# Connect to single-base mountpoint
str2str -in ntrip://rover:rtk_rover@prairiertk.polsia.app:2101/EDMO_RTCM3 \
  -out serial://ttyUSB0:115200

RTKLIB (RTKNAVI)

SettingValue
Input TypeNTRIP Client
Addressprairiertk.polsia.app
Port2101
MountpointVRS_AB
UserYour username
PasswordYour password
Send GGAYes (set interval to 10s)

Trimble / Spectra / TopCon Receivers

SettingValue
Correction SourceInternet (NTRIP)
Caster Addressprairiertk.polsia.app
Caster Port2101
MountpointVRS_AB (or select from source table)
UsernameYour username
PasswordYour password

u-blox F9P (via NTRIP client)

# Using ntripclient (Linux)
ntripclient \
  -s prairiertk.polsia.app \
  -r 2101 \
  -m VRS_AB \
  -u rover \
  -p rtk_rover \
  -D /dev/ttyACM0 \
  -n "$GPGGA,120000.00,5232.8086,N,11343.5180,W,4,12,0.8,857.0,M,0.0,M,,*5B"

Node.js (programmatic)

const net = require('net');

const socket = net.createConnection({
  host: 'prairiertk.polsia.app',
  port: 2101
}, () => {
  const auth = Buffer.from('rover:rtk_rover').toString('base64');
  const gga = '$GPGGA,142305.00,5232.8086,N,11343.5180,W,4,12,0.8,857.0,M,0.0,M,,*5B';

  socket.write(
    `GET /VRS_AB HTTP/1.1\r\n` +
    `Host: prairiertk.polsia.app\r\n` +
    `Authorization: Basic ${auth}\r\n` +
    `Ntrip-Version: Ntrip/2.0\r\n` +
    `Ntrip-GGA: ${gga}\r\n\r\n`
  );
});

socket.on('data', (data) => {
  // First response: ICY 200 OK\r\n\r\n
  // Then: continuous RTCM3 binary frames
  console.log(`Received ${data.length} bytes`);
});

socket.on('error', (err) => console.error(err.message));

Python

import socket
import base64

host = 'prairiertk.polsia.app'
port = 2101
mount = 'VRS_AB'
auth = base64.b64encode(b'rover:rtk_rover').decode()
gga = '$GPGGA,142305.00,5232.8086,N,11343.5180,W,4,12,0.8,857.0,M,0.0,M,,*5B'

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))

request = (
    f'GET /{mount} HTTP/1.1\r\n'
    f'Host: {host}\r\n'
    f'Authorization: Basic {auth}\r\n'
    f'Ntrip-Version: Ntrip/2.0\r\n'
    f'Ntrip-GGA: {gga}\r\n\r\n'
)
s.send(request.encode())

# Read response header
header = s.recv(256)
print(header.decode())

# Read RTCM3 binary frames
while True:
    data = s.recv(4096)
    if not data:
        break
    print(f'Received {len(data)} bytes of RTCM3 data')