This document describes the configuration structure of the RTCM LoRa Transmitter device as exposed through the Web UI. It serves as input for the work on redesigning the interface in Figma.
The interface is divided into 5 tabs:
| # | Tab ID | Label | Description |
|---|---|---|---|
| 1 | wifi |
WiFi | WiFi connection configuration |
| 2 | ntrip |
NTRIP | NTRIP caster configuration |
| 3 | gga |
GGA Position | Base station position (GGA) |
| 4 | lora |
LoRa Radio | LoRa radio parameters (SX1276) |
| 5 | rtcm |
RTCM Filtering | RTCM message type filtering |
| Action | Type | Behavior |
|---|---|---|
| Save & Restart | Submit (primary) | Validation → confirm dialog → POST config → device restart |
| Reload Config | Button (secondary) | Fetches the current configuration from the device |
| Restart Device | Button (danger) | Confirm dialog → device restart |
| Field | JSON Key | Type | Required | Validation | Default value | Notes |
|---|---|---|---|---|---|---|
| WiFi Network (SSID) | wifi.ssid |
string |
✅ | Non-empty | "" |
Has a “Scan” action — opens a modal with a list of available networks |
| Password | wifi.password |
string (password) |
❌ | — | "" |
Empty = open network |
| Connection Timeout | wifi.timeout |
integer (ms) |
✅ | min: 5000, max: 60000, step: 1000 | 30000 |
Additional functionality: WiFi scan modal
| Field | JSON Key | Type | Required | Validation | Default value | Notes |
|---|---|---|---|---|---|---|
| Host | ntrip.host |
string |
✅ | Non-empty | "91.198.76.2" |
|
| Port | ntrip.port |
integer |
✅ | min: 1, max: 65535 | 2101 |
|
| Username | ntrip.user |
string |
❌ | — | "" |
|
| Password | ntrip.password |
string (password) |
❌ | — | "" |
|
| Mountpoint | ntrip.mountpoint |
string |
✅ | Non-empty | "RTN4G_VRS_RTCM32" |
Has a “Fetch” action — opens a modal with a list of mountpoints |
| Connection Timeout | ntrip.timeout |
integer (ms) |
✅ | min: 5000, max: 60000, step: 1000 | 10000 |
Additional functionality: NTRIP mountpoint fetch modal
| Field | JSON Key | Type | Required | Validation | Default value | Notes |
|---|---|---|---|---|---|---|
| Latitude (°) | gga.latitude |
float |
✅ | min: -90, max: 90, step: 0.0001 | 50.2346 |
Decimal degrees, positive = North |
| Longitude (°) | gga.longitude |
float |
✅ | min: -180, max: 180, step: 0.0001 | 19.2084 |
Decimal degrees |
| Altitude (m) | gga.altitude |
float |
✅ | step: 0.1 | 266.0 |
Meters above sea level |
| Send Interval (ms) | gga.sendInterval |
integer (ms) |
✅ | min: 1000, max: 60000, step: 1000 | 2000 |
Interval for sending GGA to the NTRIP caster |
| Field | JSON Key | Type | Required | Validation | Default value | Notes |
|---|---|---|---|---|---|---|
| Frequency (MHz) | lora.frequency |
integer (Hz in API) |
✅ | min: 137 MHz, max: 1020 MHz | 433000000 (433 MHz) |
UI displays MHz, API stores Hz |
| Spreading Factor | lora.spreadingFactor |
integer (enum) |
✅ | 6–12 | 7 |
Select: SF6, SF7, SF8, SF9, SF10, SF11, SF12 |
| Bandwidth (Hz) | lora.bandwidth |
integer (enum) |
✅ | Values from the list | 125000 |
Select — see table below |
| Coding Rate | lora.codingRate |
integer (enum) |
✅ | 5–8 | 5 |
Select: 4/5, 4/6, 4/7, 4/8 |
| TX Power (dBm) | lora.txPower |
integer |
✅ | min: 2, max: 20 | 20 |
|
| Sync Word (hex) | lora.syncWord |
integer (hex) |
✅ | Format: 0x[0-9A-Fa-f]{2} |
0x12 |
UI displays hex (e.g. 0x12), API stores an integer |
Allowed Bandwidth values:
| Value (Hz) | UI Label |
|---|---|
| 7800 | 7.8 kHz |
| 10400 | 10.4 kHz |
| 15600 | 15.6 kHz |
| 20800 | 20.8 kHz |
| 31250 | 31.25 kHz |
| 41700 | 41.7 kHz |
| 62500 | 62.5 kHz |
| 125000 | 125 kHz |
| 250000 | 250 kHz |
| 500000 | 500 kHz |
| Field | JSON Key | Type | Required | Validation | Default value | Notes |
|---|---|---|---|---|---|---|
| Allowed Message Types | rtcm.messageTypes |
array<integer> |
✅ | Min 1 element | [1005, 1007, 1019, 1020, 1033, 1075, 1085, 1095, 1125, 1230] |
UI: textarea, comma-separated |
| High Priority Types | rtcm.priorityMessageTypes |
array<integer> |
❌ | — | [1005, 1075, 1085, 1095, 1125, 1230] |
UI: textarea, comma-separated; Types transmitted with higher priority |
All endpoints are available over HTTP on port 80 (Access Point).
GET /api/config — Fetch configurationResponse 200 OK — application/json
{
"wifi": {
"ssid": "string",
"password": "string",
"timeout": 30000
},
"ntrip": {
"host": "string",
"port": 2101,
"mountpoint": "string",
"user": "string",
"password": "string",
"timeout": 10000
},
"gga": {
"latitude": 50.2346,
"longitude": 19.2084,
"altitude": 266.0,
"sendInterval": 2000
},
"lora": {
"frequency": 433000000,
"spreadingFactor": 7,
"bandwidth": 125000,
"codingRate": 5,
"txPower": 20,
"syncWord": 18
},
"rtcm": {
"messageTypes": [
1005, 1007, 1019, 1020, 1033, 1075, 1085, 1095, 1125, 1230
],
"priorityMessageTypes": [1005, 1075, 1085, 1095, 1125, 1230]
},
"display": {
"updateInterval": 500
}
}
Note: The
displaysection is present in the API but is not exposed in the current UI.
POST /api/config — Save configurationRequest — Content-Type: application/json
Body: the same structure as the response from GET /api/config. All sections are optional — the sections sent overwrite the existing configuration, while omitted sections remain unchanged.
Response 200 OK:
{ "success": true, "message": "Configuration saved. Device will restart." }
Response 400 Bad Request:
{ "success": false, "message": "Invalid JSON" }
{ "success": false, "message": "No data received" }
Response 500 Internal Server Error:
{ "success": false, "message": "Failed to save configuration" }
Behavior: After a successful save, the device automatically restarts after ~1s.
POST /api/restart — Restart the deviceRequest: Empty body.
Response 200 OK:
{ "success": true, "message": "Device restarting..." }
POST /api/wifi/scan — Scan WiFi networksRequest: Empty body.
Response 200 OK:
{
"success": true,
"networks": [
{
"ssid": "MyNetwork",
"bssid": "AA:BB:CC:DD:EE:FF",
"rssi": -45,
"encryption": "secured",
"channel": 6
}
]
}
| Field | Type | Description |
|---|---|---|
ssid |
string |
Network name |
bssid |
string |
Access point MAC address (format: XX:XX:XX:XX:XX:XX) |
rssi |
integer |
Signal strength in dBm (higher = better) |
encryption |
string |
"open" or "secured" |
channel |
integer |
WiFi channel |
Response 500:
{ "success": false, "message": "Scan failed" }
POST /api/ntrip/mountpoints — Fetch NTRIP mountpointsRequest — Content-Type: application/x-www-form-urlencoded
| Parameter | Required | Description |
|---|---|---|
host |
✅ | NTRIP caster host address |
port |
✅ | Caster port |
user |
❌ | Login (if required) |
password |
❌ | Password (if required) |
Response 200 OK:
{
"mountpoints": ["RTN4G_VRS_RTCM32", "NEAREST_RTN", "VRS_3_2"]
}
Response 200 OK (error):
{ "error": "Connection failed" }
Response 400 Bad Request:
{ "error": "Missing host or port parameter" }
Validation happens before the form is submitted. List of rules:
| Rule | Error message |
|---|---|
wifi.ssid is empty |
“WiFi SSID is required” |
ntrip.host is empty |
“NTRIP host is required” |
ntrip.port < 1 or > 65535 |
“NTRIP port must be between 1 and 65535” |
gga.latitude < -90 or > 90 |
“Latitude must be between -90 and 90” |
gga.longitude < -180 or > 180 |
“Longitude must be between -180 and 180” |
lora.frequency < 137 MHz or > 1020 MHz |
“LoRa frequency out of valid range (137–1020 MHz)” |
lora.spreadingFactor < 6 or > 12 |
“Spreading factor must be between 6 and 12” |
lora.txPower < 2 or > 20 |
“TX power must be between 2 and 20 dBm” |
rtcm.messageTypes is empty |
“At least one RTCM message type must be configured” |
Note: Validation exists only on the UI side. The backend does not validate values — it accepts whatever it receives in valid JSON.
| Field | UI format | API format | Conversion |
|---|---|---|---|
lora.frequency |
MHz (e.g. 433.085) |
Hz (e.g. 433085000) |
UI→API: × 1e6, API→UI: ÷ 1e6 |
lora.syncWord |
Hex string (e.g. 0x12) |
Integer (e.g. 18) |
UI→API: parseInt(val, 16), API→UI: "0x" + val.toString(16) |
rtcm.messageTypes |
Comma-separated string (e.g. "1005, 1075") |
Array of integers (e.g. [1005, 1075]) |
UI→API: split + parseInt, API→UI: join |
rtcm.priorityMessageTypes |
Comma-separated string | Array of integers | same as above |
OSS-LoRa-TX-XXXX (where XXXX = the last 4 characters of the MAC)http://192.168.4.1/