Open Ba0Nguyen opened 2 months ago
@Ba0Nguyen - the HttpURLConnection
probably isn't the best way. Ntrip is almost http, but its differences seem to often make standard Http libraries unhappy. Here's a quick java application that should connect, send in a message, and print out the returned corrections.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Base64;
public class NtripClient {
public static void main(String[] args) {
// Read environmental variables
String ntripCasterHost = System.getenv("NTRIP_CASTER_HOST");
String ntripCasterPort = System.getenv("NTRIP_CASTER_PORT");
String ntripMountPoint = System.getenv("NTRIP_MOUNT_POINT");
String username = System.getenv("NTRIP_USERNAME");
String password = System.getenv("NTRIP_PASSWORD");
String latitudeStr = System.getenv("LATITUDE");
String longitudeStr = System.getenv("LONGITUDE");
if (ntripCasterHost == null || ntripCasterPort == null || ntripMountPoint == null || username == null || password == null || latitudeStr == null || longitudeStr == null) {
System.err.println("Environmental variables NTRIP_CASTER_HOST, NTRIP_CASTER_PORT, NTRIP_MOUNT_POINT, NTRIP_USERNAME, NTRIP_PASSWORD, LATITUDE, and LONGITUDE must be set.");
return;
}
int port = Integer.parseInt(ntripCasterPort);
double latitude = Double.parseDouble(latitudeStr);
double longitude = Double.parseDouble(longitudeStr);
try {
// Create a socket connection to the NTRIP caster
Socket socket = new Socket(ntripCasterHost, port);
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// Send NTRIP request
String auth = username + ":" + password;
String encodedAuth = Base64.getEncoder().encodeToString(auth.getBytes());
writer.write("GET /" + ntripMountPoint + " HTTP/1.1\r\n");
writer.write("Host: " + ntripCasterHost + "\r\n");
writer.write("Ntrip-Version: Ntrip/2.0\r\n");
writer.write("User-Agent: NTRIP NtripClient\r\n");
writer.write("Authorization: Basic " + encodedAuth + "\r\n");
writer.write("\r\n");
writer.flush();
// Create and send GGA message
String ggaMessage = createGgaMessage(latitude, longitude);
System.out.println("Sending GGA message: " + ggaMessage.trim()); // Debug line
writer.write(ggaMessage);
writer.flush();
// Read response header
String responseLine;
while ((responseLine = reader.readLine()) != null && !responseLine.isEmpty()) {
System.out.println(responseLine);
}
// Read GNSS correction data
InputStream inputStream = socket.getInputStream();
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = inputStream.read(buffer)) != -1) {
// Output the binary data
for (int i = 0; i < bytesRead; i++) {
System.out.printf("%02x ", buffer[i]);
}
System.out.println();
}
// Close the streams
reader.close();
writer.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static String createGgaMessage(double latitude, double longitude) {
String latDirection = latitude >= 0 ? "N" : "S";
String lonDirection = longitude >= 0 ? "E" : "W";
latitude = Math.abs(latitude);
longitude = Math.abs(longitude);
int latDegrees = (int) latitude;
double latMinutes = (latitude - latDegrees) * 60.0;
int lonDegrees = (int) longitude;
double lonMinutes = (longitude - lonDegrees) * 60.0;
String gga = String.format(
"$GPGGA,123519,%02d%07.4f,%s,%03d%07.4f,%s,1,08,0.9,545.4,M,46.9,M,,",
latDegrees, latMinutes, latDirection, lonDegrees, lonMinutes, lonDirection
);
String checksum = calculateChecksum(gga);
return gga + "*" + checksum + "\r\n";
}
private static String calculateChecksum(String sentence) {
int checksum = 0;
for (int i = 1; i < sentence.length(); i++) {
checksum ^= sentence.charAt(i);
}
return String.format("%02X", checksum);
}
}
This will run on its own and print out the correction data as bytes. I tested this with the following ENV variables
LATITUDE=37.788;
LONGITUDE=-122.402;
NTRIP_CASTER_HOST=polaris.pointonenav.com;
NTRIP_CASTER_PORT=2101;
NTRIP_MOUNT_POINT=POLARIS;
NTRIP_PASSWORD=<YOUR_NTRIP_PASSWORD>;
NTRIP_USERNAME=<YOUR_NTRIP_USERNAME>;
Hope this helps!
Thanks for the help @mkurdziel , Do you have any documentation for the RTCM data format (e.g. rtcm type)? I would like to parse and convert it to each RTCM String.
I was able to forward RTCM data to my drone, can you direct me to how I can achieve 1cm accuracy? Do I have to update my position a certain way to achieve that? Does the mount point I am using support 1cm accuracy? I've tried mount point POLARIS_LOCAL and is getting 4cm accuracy. I also noticed that if I start to move to drone, accuracy can get worse.
` val urlString = "https://polaris.pointonenav.com:2101\n"
`
I used to code above to attempt to connect to Polaris NTRIP Server but failed to do so. Do I need any header or sending initial message to connect with Polaris NTRIP ?