first working serial nmea parser
This commit is contained in:
parent
17b8ba745b
commit
031df4b3ca
|
@ -4,7 +4,7 @@ android {
|
|||
compileSdkVersion 30
|
||||
defaultConfig {
|
||||
applicationId "hendrikschutter.com.externgnss"
|
||||
minSdkVersion 17
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 30
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
|
|
@ -2,13 +2,7 @@ package hendrikschutter.com.externgnss;
|
|||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbManager;
|
||||
import android.location.LocationListener;
|
||||
import android.location.LocationManager;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
@ -23,36 +17,31 @@ import pub.devrel.easypermissions.EasyPermissions;
|
|||
|
||||
import static java.lang.Thread.sleep;
|
||||
|
||||
import com.hoho.android.usbserial.driver.UsbSerialDriver;
|
||||
import com.hoho.android.usbserial.driver.UsbSerialPort;
|
||||
import com.hoho.android.usbserial.driver.UsbSerialProber;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private TextView output;
|
||||
private LocationManager locationManager;
|
||||
private LocationManager locationManager= null;
|
||||
private SerialUSB serialUSB = null;
|
||||
private NMEAParser nmeaParser = null;
|
||||
private boolean doRun = true;
|
||||
private final Context cntxToastInternGNSSUpdate = this;
|
||||
final String[] perms = {Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.INTERNET,};
|
||||
private static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
|
||||
private boolean bChange = true;
|
||||
private BlockingQueue<Byte> rawSerialByteDataQueue = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
startLocationInit();
|
||||
|
||||
SerialUSB serialUSB = new SerialUSB(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// start intern GNSS and display stats on UI
|
||||
startInternGNSS();
|
||||
|
||||
// start extern GNSS and display stats on UI
|
||||
startExternGNSS();
|
||||
}
|
||||
|
||||
// From https://github.com/googlesamples/easypermissions
|
||||
|
@ -63,44 +52,33 @@ public class MainActivity extends AppCompatActivity {
|
|||
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
|
||||
}
|
||||
|
||||
|
||||
private void startExternGNSS(){
|
||||
rawSerialByteDataQueue = new LinkedBlockingQueue<>();
|
||||
serialUSB = new SerialUSB(this, rawSerialByteDataQueue);
|
||||
|
||||
if(serialUSB.findSerialDevice()){
|
||||
serialUSB.connect(9600, 0);
|
||||
if (serialUSB.isConnected()){
|
||||
nmeaParser = new NMEAParser();
|
||||
nmeaParser.setReceiveByteStream(rawSerialByteDataQueue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AfterPermissionGranted(123)
|
||||
private void startLocationInit() {
|
||||
private void startInternGNSS() {
|
||||
if (EasyPermissions.hasPermissions(this, perms)) {
|
||||
// Already have permission, do the thing
|
||||
Toast.makeText(cntxToastInternGNSSUpdate, "Permission granted!", Toast.LENGTH_SHORT).show();
|
||||
|
||||
// Get the output UI
|
||||
// output = (TextView) findViewById(R.id.interngnssLongTextView);
|
||||
|
||||
// Test print
|
||||
///printlnOnView(output, "Running!");
|
||||
|
||||
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
|
||||
//List<String> providers = locationManager.getAllProviders();
|
||||
|
||||
//for (String temp : providers) {
|
||||
// System.out.println(temp);
|
||||
//printProvider(temp);
|
||||
//}
|
||||
|
||||
} else {
|
||||
// Do not have permissions, request them now
|
||||
EasyPermissions.requestPermissions(this, "We require location access!!!",
|
||||
EasyPermissions.requestPermissions(this, "We require location access!",
|
||||
123, perms);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
private void printProvider(String provider) {
|
||||
LocationProvider info = locationManager.getProvider(provider);
|
||||
output.append("Name: " + info.getName() + "\n");
|
||||
output.append("Accuracy: " + info.getAccuracy() + "\n");
|
||||
output.append("PowerReq.: " + info.getPowerRequirement() + "\n");
|
||||
output.append("CellIDReq.: " + info.requiresCell() + "\n");
|
||||
output.append("NetworkReq.: " + info.requiresNetwork() + "\n");
|
||||
output.append("SatReq.: " + info.requiresSatellite() + "\n\n");
|
||||
}
|
||||
*/
|
||||
|
||||
private void setEditTextLabel(final EditText v, final String str) {
|
||||
Runnable myRun = new Runnable() {
|
||||
|
@ -110,39 +88,6 @@ public class MainActivity extends AppCompatActivity {
|
|||
};
|
||||
runOnUiThread(myRun);
|
||||
}
|
||||
/*
|
||||
private void printOnView(final TextView v, final String str) {
|
||||
Runnable myRun = new Runnable() {
|
||||
public void run() {
|
||||
v.append(str);
|
||||
}
|
||||
};
|
||||
runOnUiThread(myRun);
|
||||
}
|
||||
|
||||
public void addToString(Location loc) {
|
||||
//Verwendet die Variablen centerLat & centerLng
|
||||
String time = loc.getTime() +"";
|
||||
String latStr = Double.toString(loc.getLatitude());
|
||||
String lngStr = Double.toString(loc.getLongitude());
|
||||
String acc = loc.getAccuracy() + "";
|
||||
String numOfSat = loc.getExtras().getInt("satellites") +"";
|
||||
String satStr = "";
|
||||
String distStr = "";
|
||||
// Bestimme die Distanz (Fix <-> Center)
|
||||
Location locationA = new Location("Center");
|
||||
locationA.setLatitude(Double.valueOf(centerLat));
|
||||
locationA.setLongitude(Double.valueOf(centerLng));
|
||||
Location locationB = new Location("Fix");
|
||||
locationB.setLatitude(Double.valueOf(latStr));
|
||||
locationB.setLongitude(Double.valueOf(lngStr));
|
||||
distStr = locationA.distanceTo(locationB) + "";
|
||||
logString = logString + time + ";"; logString = logString + numOfSat + ";"; logString = logString + distStr +
|
||||
";"; logString = logString + acc + ";"; logString = logString + latStr + ";"; logString = logString + lngStr
|
||||
+ ";"; logString = logString + centerLat + ";"; logString = logString + centerLng + ";"; logString =
|
||||
logString + satStr + ";"; logString = logString + "\n";
|
||||
}
|
||||
*/
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
@Override
|
||||
|
@ -185,6 +130,24 @@ public class MainActivity extends AppCompatActivity {
|
|||
setEditTextLabel((EditText) findViewById(R.id.interngnssAccuracyNumber), "no signal");
|
||||
setEditTextLabel((EditText) findViewById(R.id.interngnssSatCountNumber),"no signal");
|
||||
}
|
||||
|
||||
if(serialUSB != null){
|
||||
if(serialUSB.isConnected()){
|
||||
nmeaParser.handleReceiveByteStream();
|
||||
if (nmeaParser.checkFix() == true) {
|
||||
//System.out.println(parser.getLatitude() + " " + parser.getLongitude());
|
||||
//System.out.println(parser.calcDistance(fixedPosLat, fixedPosLng));
|
||||
|
||||
//nmeaParser.getLatitude();
|
||||
//nmeaParser.getLongitude();
|
||||
Log.i("ExternGNSS", "Fix! Lat: " + String.valueOf(nmeaParser.getLatitude()) + " Lon: " + String.valueOf(nmeaParser.getLongitude()));
|
||||
|
||||
// distance.add(nmeaParser.calcDistance(fixedPosLat, fixedPosLng));
|
||||
// satCount.add(nmeaParser.getSatCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -214,9 +177,6 @@ public class MainActivity extends AppCompatActivity {
|
|||
LocationListener locationListener = new LocationListener() {
|
||||
@Override
|
||||
public void onLocationChanged(android.location.Location location) {
|
||||
//double latitude = location.getLatitude();
|
||||
//double longitude = location.getLongitude();
|
||||
//String msg = "New Latitude: " + latitude + " New Longitude: " + longitude;
|
||||
Toast.makeText(cntxToastInternGNSSUpdate, "Internal GNSS updated", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,121 @@
|
|||
package hendrikschutter.com.externgnss;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class NMEAParser {
|
||||
private double latitude;
|
||||
private double longitude;
|
||||
private boolean fix;
|
||||
private int satCount;
|
||||
private BlockingQueue<Byte> rawByteData = null;
|
||||
|
||||
public NMEAParser() {
|
||||
this.fix = false;
|
||||
this.satCount = 0;
|
||||
this.latitude = 0;
|
||||
this.longitude = 0;
|
||||
}
|
||||
|
||||
public void setReceiveByteStream(BlockingQueue<Byte> rawData) {
|
||||
this.rawByteData = rawData;
|
||||
}
|
||||
|
||||
/**
|
||||
* find strings in raw data and sent them to parse
|
||||
*/
|
||||
public void handleReceiveByteStream() {
|
||||
String nmeaSentence;
|
||||
ByteArrayOutputStream rawDataByteStream = new ByteArrayOutputStream();
|
||||
|
||||
//wait for sufficient data in buffer TODO don't do this block wise, losing data in edge
|
||||
if (this.rawByteData.size() > 512) {
|
||||
for (Iterator<Byte> rawByte = this.rawByteData.iterator(); rawByte.hasNext(); ) {
|
||||
rawDataByteStream.write(rawByte.next());
|
||||
rawByte.remove(); //remove this data from stream
|
||||
}
|
||||
ByteArrayInputStream stream = new ByteArrayInputStream(rawDataByteStream.toByteArray());
|
||||
InputStreamReader streamReader = new InputStreamReader(stream, StandardCharsets.US_ASCII);
|
||||
BufferedReader bufferedReader = new BufferedReader(streamReader);
|
||||
|
||||
try {
|
||||
while ((nmeaSentence = bufferedReader.readLine()) != null) {
|
||||
//Log.i("NMEAParser", nmeaSentence);
|
||||
this.parseSentence(nmeaSentence);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
//Log.i("NMEAParser", "wait for more data in buffer");
|
||||
}
|
||||
}
|
||||
|
||||
public void parseSentence(String sentence) {
|
||||
if (sentence.startsWith("$GNGLL")) {
|
||||
parseGNGLL(sentence);
|
||||
}
|
||||
if (sentence.startsWith("$GPGSV")) {
|
||||
parseGPGSV(sentence);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseGNGLL(String sentence) {
|
||||
if (sentence.length() >= 45) {
|
||||
if (sentence.substring(44, 45).equals("A")) {
|
||||
this.fix = true;
|
||||
this.latitude = (Double.parseDouble(sentence.substring(9, 17)) / 60) + Double.parseDouble(sentence.substring(7, 9));
|
||||
this.longitude = (Double.parseDouble(sentence.substring(23, 30)) / 60) + Double.parseDouble(sentence.substring(20, 23));
|
||||
} else {
|
||||
this.fix = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseGPGSV(String sentence) {
|
||||
if (sentence.length() >= 13) {
|
||||
this.satCount = (Integer.parseInt(sentence.substring(11, 13)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public double calcDistance(double latitude, double longitude) {
|
||||
final int R = 6371; // Radius of the earth
|
||||
|
||||
double latDistance = Math.toRadians(latitude - this.latitude);
|
||||
double lonDistance = Math.toRadians(longitude - this.longitude);
|
||||
double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
|
||||
+ Math.cos(Math.toRadians(this.latitude)) * Math.cos(Math.toRadians(latitude))
|
||||
* Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
|
||||
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
double distance = R * c * 1000; // convert to meters
|
||||
distance = Math.pow(distance, 2);
|
||||
return Math.sqrt(distance);
|
||||
}
|
||||
|
||||
|
||||
public double getLatitude() {
|
||||
return this.latitude;
|
||||
}
|
||||
|
||||
public double getLongitude() {
|
||||
return this.longitude;
|
||||
}
|
||||
|
||||
public boolean checkFix() {
|
||||
return this.fix;
|
||||
}
|
||||
|
||||
public int getSatCount() {
|
||||
return this.satCount;
|
||||
}
|
||||
}
|
|
@ -4,7 +4,6 @@ import android.app.PendingIntent;
|
|||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.hardware.usb.UsbDevice;
|
||||
import android.hardware.usb.UsbDeviceConnection;
|
||||
import android.hardware.usb.UsbManager;
|
||||
|
@ -16,69 +15,59 @@ import com.hoho.android.usbserial.driver.UsbSerialProber;
|
|||
import com.hoho.android.usbserial.util.SerialInputOutputManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
|
||||
public class SerialUSB implements SerialInputOutputManager.Listener{
|
||||
|
||||
private MainActivity mainActivity = null;
|
||||
|
||||
private enum UsbPermission { Unknown, Requested, Granted, Denied }
|
||||
|
||||
private static final String INTENT_ACTION_GRANT_USB = BuildConfig.APPLICATION_ID + ".GRANT_USB";
|
||||
private static final int WRITE_WAIT_MILLIS = 2000;
|
||||
private static final int READ_WAIT_MILLIS = 2000;
|
||||
|
||||
private int deviceId, portNum, baudRate;
|
||||
private boolean withIoManager;
|
||||
|
||||
private BroadcastReceiver broadcastReceiver = null;
|
||||
//private final Handler mainLooper;
|
||||
//private TextView receiveText;
|
||||
//private ControlLines controlLines;
|
||||
|
||||
private SerialInputOutputManager usbIoManager;
|
||||
private UsbSerialPort usbSerialPort;
|
||||
private UsbPermission usbPermission = UsbPermission.Unknown;
|
||||
private BlockingQueue<Byte> dataBytesQueue = null;
|
||||
private boolean connected = false;
|
||||
|
||||
public SerialUSB(MainActivity mainActivity){
|
||||
public SerialUSB(MainActivity mainActivity, BlockingQueue<Byte> dataBytesQueue){
|
||||
this.mainActivity = mainActivity;
|
||||
this.dataBytesQueue = dataBytesQueue;
|
||||
}
|
||||
|
||||
public boolean isConnected(){
|
||||
return connected;
|
||||
}
|
||||
|
||||
public boolean findSerialDevice(){
|
||||
// Find all available drivers from attached devices.
|
||||
UsbManager usbManager = (UsbManager) this.mainActivity.getSystemService(Context.USB_SERVICE);
|
||||
UsbSerialProber usbDefaultProber = UsbSerialProber.getDefaultProber();
|
||||
boolean deviceFound = false;
|
||||
|
||||
if (usbManager.getDeviceList().values().size() > 0){
|
||||
UsbDevice device = (UsbDevice) usbManager.getDeviceList().values().toArray()[0];
|
||||
UsbSerialDriver driver = usbDefaultProber.probeDevice(device);
|
||||
if(driver == null) {
|
||||
Log.i("SerialUSB", "driver is null");
|
||||
}
|
||||
if(driver != null) {
|
||||
Log.i("SerialUSB", "ExternGNSS: device/driver found!");
|
||||
this.deviceId = device.getDeviceId();
|
||||
this.portNum = 0;
|
||||
this.baudRate = 9600;
|
||||
this.withIoManager = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
broadcastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if(INTENT_ACTION_GRANT_USB.equals(intent.getAction())) {
|
||||
usbPermission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false) ? UsbPermission.Granted : UsbPermission.Denied;
|
||||
connect();
|
||||
} else {
|
||||
Log.i("SerialUSB", "USB permissions are not set");
|
||||
}
|
||||
//check of at least one device is present
|
||||
if (usbManager.getDeviceList().values().size() > 0){
|
||||
//get fist device
|
||||
UsbDevice device = (UsbDevice) usbManager.getDeviceList().values().toArray()[0];
|
||||
UsbSerialDriver driver = usbDefaultProber.probeDevice(device);
|
||||
if(driver == null) {
|
||||
Log.e("SerialUSB", "driver is null");
|
||||
}
|
||||
};
|
||||
connect();
|
||||
this.mainActivity.registerReceiver(broadcastReceiver, new IntentFilter(INTENT_ACTION_GRANT_USB));
|
||||
if(driver != null) {
|
||||
Log.i("SerialUSB", "ExternGNSS: device/driver found!");
|
||||
this.deviceId = device.getDeviceId();
|
||||
deviceFound = true;
|
||||
}
|
||||
} else
|
||||
{
|
||||
Log.e("SerialUSB", "no serial device connected");
|
||||
deviceFound = false;
|
||||
}
|
||||
return deviceFound;
|
||||
}
|
||||
|
||||
private void connect() {
|
||||
public void connect(int baudRate, int portNum) {
|
||||
this.baudRate = baudRate;
|
||||
this.portNum = portNum;
|
||||
Log.i("connect", "starting to connect ...");
|
||||
UsbDevice device = null;
|
||||
UsbManager usbManager = (UsbManager) this.mainActivity.getSystemService(Context.USB_SERVICE);
|
||||
|
@ -90,11 +79,6 @@ public class SerialUSB implements SerialInputOutputManager.Listener{
|
|||
return;
|
||||
}
|
||||
UsbSerialDriver driver = UsbSerialProber.getDefaultProber().probeDevice(device);
|
||||
/*
|
||||
if(driver == null) {
|
||||
driver = CustomProber.getCustomProber().probeDevice(device);
|
||||
}
|
||||
*/
|
||||
if(driver == null) {
|
||||
Log.i("connect", "connection failed: no driver for device");
|
||||
return;
|
||||
|
@ -118,27 +102,21 @@ public class SerialUSB implements SerialInputOutputManager.Listener{
|
|||
Log.i("connect", "connection failed: open failed");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
usbSerialPort.open(usbConnection);
|
||||
usbSerialPort.setParameters(baudRate, 8, 1, UsbSerialPort.PARITY_NONE);
|
||||
if(withIoManager) {
|
||||
usbIoManager = new SerialInputOutputManager(usbSerialPort, this);
|
||||
usbIoManager.start();
|
||||
}
|
||||
|
||||
Log.i("connect", "connected");
|
||||
connected = true;
|
||||
//controlLines.start();
|
||||
} catch (Exception e) {
|
||||
Log.i("connect", "connection failed: " + e.getMessage());
|
||||
disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
private void disconnect() {
|
||||
public void disconnect() {
|
||||
connected = false;
|
||||
//controlLines.stop();
|
||||
if(usbIoManager != null) {
|
||||
usbIoManager.setListener(null);
|
||||
usbIoManager.stop();
|
||||
|
@ -152,7 +130,11 @@ public class SerialUSB implements SerialInputOutputManager.Listener{
|
|||
|
||||
@Override
|
||||
public void onNewData(byte[] data) {
|
||||
Log.i("connect", "received data: " + data.length);
|
||||
//Log.i("connect", "received data: " + data.length);
|
||||
//Log.i("connect", new String(data, StandardCharsets.US_ASCII) );
|
||||
for (byte rawByte : data) {
|
||||
this.dataBytesQueue.add(rawByte);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in New Issue