mirror of
https://github.com/eclipse-sailing-analytics/sailing-analytics.git
synced 2026-10-08 05:11:04 +00:00
first working parser for SwissTiming GPS packets with test case
This commit is contained in:
1 parent
ac8508e5f8
commit
66c031ccf4
12 files changed
+205
-11
No files matched your search
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry exported="true" kind="lib" path="resources/"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
|
||||
@@ -6,4 +6,7 @@ Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Require-Bundle: com.sap.sailing.domain.swisstimingadapter,
|
||||
com.sap.sailing.domain
|
||||
com.sap.sailing.domain,
|
||||
org.junit4
|
||||
Bundle-ClassPath: resources/,
|
||||
.
|
||||
@@ -0,0 +1,5 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
resources/
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>root</artifactId>
|
||||
<groupId>com.sap.sailing</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>com.sap.sailing.domain.swisstimingadapter.test</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>eclipse-test-plugin</packaging>
|
||||
</project>
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFormatException;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingMessage;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingMessageParser;
|
||||
|
||||
public class ParseSingleSwissTimingPacketFromFile {
|
||||
@Test
|
||||
public void readSinglePacketFromFile() throws IOException, SwissTimingFormatException {
|
||||
byte[] message = new byte[65536];
|
||||
InputStream is = getClass().getResourceAsStream("/SwissTimingExampleTrack.bin");
|
||||
is.read(message);
|
||||
SwissTimingMessage swissTimingMessage = SwissTimingMessageParser.INSTANCE.parse(message);
|
||||
assertNotNull(swissTimingMessage);
|
||||
int lat = ((0x1e<<8 | 0x2c)<<8 | 0x31)<<8 | 0x14;
|
||||
int lng = ((0xfe << 8 | 0x97)<<8 | 0x1d)<<8 | 0x73;
|
||||
assertEquals((double) lat / 10000000., swissTimingMessage.getPosition().getLatDeg(), 0.0000000001);
|
||||
assertEquals((double) lng / 10000000., swissTimingMessage.getPosition().getLngDeg(), 0.0000000001);
|
||||
}
|
||||
}
|
||||
@@ -6,3 +6,4 @@ Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: SAP
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||
Require-Bundle: com.sap.sailing.domain
|
||||
Export-Package: com.sap.sailing.domain.swisstimingadapter
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>root</artifactId>
|
||||
<groupId>com.sap.sailing</groupId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>com.sap.sailing.domain.swisstimingadapter</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</project>
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
public class SwissTimingFormatException extends Exception {
|
||||
private static final long serialVersionUID = -1210353206288437237L;
|
||||
|
||||
private final byte[] swissTimingMessage;
|
||||
|
||||
public SwissTimingFormatException(String errorMessage, byte[] swissTimingMessage) {
|
||||
super(errorMessage);
|
||||
this.swissTimingMessage = swissTimingMessage;
|
||||
}
|
||||
|
||||
public byte[] getSwissTimingMessage() {
|
||||
return swissTimingMessage;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import com.sap.sailing.domain.base.Position;
|
||||
import com.sap.sailing.domain.base.Speed;
|
||||
import com.sap.sailing.domain.base.TimePoint;
|
||||
|
||||
public interface SwissTimingMessage {
|
||||
String getRaceID();
|
||||
|
||||
int getPacketID();
|
||||
|
||||
TimePoint getTimestamp();
|
||||
|
||||
int getGpsID();
|
||||
|
||||
Position getPosition();
|
||||
|
||||
Speed getSpeed();
|
||||
|
||||
int getNumberOfSatellites();
|
||||
|
||||
int getBatteryPercent();
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
|
||||
import com.sap.sailing.domain.swisstimingadapter.impl.SwissTimingMessageParserImpl;
|
||||
|
||||
public interface SwissTimingMessageParser {
|
||||
SwissTimingMessageParser INSTANCE = new SwissTimingMessageParserImpl();
|
||||
|
||||
SwissTimingMessage parse(byte[] message) throws SwissTimingFormatException;
|
||||
}
|
||||
+11
-10
@@ -1,21 +1,22 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter;
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.Position;
|
||||
import com.sap.sailing.domain.base.Speed;
|
||||
import com.sap.sailing.domain.base.TimePoint;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingMessage;
|
||||
|
||||
public class GPSFix {
|
||||
public class SwissTimingMessageImpl implements SwissTimingMessage {
|
||||
private final String raceID;
|
||||
private final int packetID;
|
||||
private final TimePoint timestamp;
|
||||
private final short gpsID;
|
||||
private final int gpsID;
|
||||
private final Position position;
|
||||
private final Speed speed;
|
||||
private final byte numberOfSatellites;
|
||||
private final byte batteryPercent;
|
||||
private final int numberOfSatellites;
|
||||
private final int batteryPercent;
|
||||
|
||||
public GPSFix(String raceID, int packetID, TimePoint timestamp, short gpsID, Position position, Speed speed,
|
||||
byte numberOfSatellites, byte batteryPercent) {
|
||||
public SwissTimingMessageImpl(String raceID, int packetID, TimePoint timestamp, int gpsID, Position position, Speed speed,
|
||||
int numberOfSatellites, int batteryPercent) {
|
||||
super();
|
||||
this.raceID = raceID;
|
||||
this.packetID = packetID;
|
||||
@@ -39,7 +40,7 @@ public class GPSFix {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public short getGpsID() {
|
||||
public int getGpsID() {
|
||||
return gpsID;
|
||||
}
|
||||
|
||||
@@ -51,11 +52,11 @@ public class GPSFix {
|
||||
return speed;
|
||||
}
|
||||
|
||||
public byte getNumberOfSatellites() {
|
||||
public int getNumberOfSatellites() {
|
||||
return numberOfSatellites;
|
||||
}
|
||||
|
||||
public byte getBatteryPercent() {
|
||||
public int getBatteryPercent() {
|
||||
return batteryPercent;
|
||||
}
|
||||
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
package com.sap.sailing.domain.swisstimingadapter.impl;
|
||||
|
||||
import com.sap.sailing.domain.base.impl.DegreeBearingImpl;
|
||||
import com.sap.sailing.domain.base.impl.DegreePosition;
|
||||
import com.sap.sailing.domain.base.impl.KilometersPerHourSpeedWithBearingImpl;
|
||||
import com.sap.sailing.domain.base.impl.MillisecondsTimePoint;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingFormatException;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingMessage;
|
||||
import com.sap.sailing.domain.swisstimingadapter.SwissTimingMessageParser;
|
||||
|
||||
public class SwissTimingMessageParserImpl implements SwissTimingMessageParser {
|
||||
|
||||
@Override
|
||||
public SwissTimingMessage parse(byte[] message) throws SwissTimingFormatException {
|
||||
int i=0;
|
||||
if (message[i] != 0x10 || message[i+1] != 0x00) {
|
||||
throw new SwissTimingFormatException("Didn't find start marker 0x1000", message);
|
||||
}
|
||||
i+=2;
|
||||
String raceID = new String(message, i, 9);
|
||||
i+=9;
|
||||
int packetID = parseInt(message, i);
|
||||
i+=4;
|
||||
long timestamp = parseLong(message, i);
|
||||
i+=8;
|
||||
byte packetType = message[i];
|
||||
if (packetType != 0x02) {
|
||||
throw new SwissTimingFormatException("Expected to find package type 0x02", message);
|
||||
}
|
||||
i+=1;
|
||||
short gpsID = parseShort(message, i);
|
||||
i+=2;
|
||||
int longitude = parseInt(message, i);
|
||||
i+=4;
|
||||
int latitude = parseInt(message, i);
|
||||
i+=4;
|
||||
int speedInDecimetersPerSecond = 0xFF & message[i];
|
||||
i+=1;
|
||||
int course = parseShort(message, i);
|
||||
i+=2;
|
||||
int numberOfSatellites = (message[i] & 0xF0) >> 4;
|
||||
int batteryPercent = 10 * (message[i] & 0x0F);
|
||||
i+=1;
|
||||
if (message[i] != 0x10 || message[i+1] != 0x30) {
|
||||
throw new SwissTimingFormatException("Didn't find end marker 0x1030", message);
|
||||
}
|
||||
i+=2;
|
||||
return new SwissTimingMessageImpl(raceID, packetID, new MillisecondsTimePoint(timestamp), gpsID,
|
||||
new DegreePosition((double) latitude / 10000000., (double) longitude / 10000000.),
|
||||
new KilometersPerHourSpeedWithBearingImpl(0.36*speedInDecimetersPerSecond, new DegreeBearingImpl(course)),
|
||||
numberOfSatellites, batteryPercent);
|
||||
}
|
||||
|
||||
private short parseShort(byte[] message, int offset) {
|
||||
short result = 0;
|
||||
for (int b=0; b<2; b++) {
|
||||
result <<= 8;
|
||||
result += (0xFF & message[offset+b]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private long parseLong(byte[] message, int offset) {
|
||||
long result = 0l;
|
||||
for (int b=0; b<8; b++) {
|
||||
result <<= 8;
|
||||
result += (0xFF & message[offset+b]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private int parseInt(byte[] message, int offset) {
|
||||
int result = 0;
|
||||
for (int b=0; b<4; b++) {
|
||||
result <<= 8;
|
||||
result += (0xFF & message[offset+b]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user