2022-04-25 17:11:58 +02:00
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 ;
2022-04-25 22:55:07 +02:00
private int sentenceCounter ;
2022-04-25 17:11:58 +02:00
private BlockingQueue < Byte > rawByteData = null ;
public NMEAParser ( ) {
this . fix = false ;
this . satCount = 0 ;
this . latitude = 0 ;
this . longitude = 0 ;
2022-04-25 22:55:07 +02:00
this . sentenceCounter = 0 ;
2022-04-25 17:11:58 +02:00
}
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");
}
}
2022-04-25 22:55:07 +02:00
public int getSentenceCounter ( ) {
return this . sentenceCounter ;
}
2022-04-25 17:11:58 +02:00
public void parseSentence ( String sentence ) {
2022-04-25 22:55:07 +02:00
this . sentenceCounter + + ;
2022-04-25 17:11:58 +02:00
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 ;
}
}