aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAnton Tananaev <anton@traccar.org>2022-09-18 10:01:28 -0700
committerAnton Tananaev <anton@traccar.org>2022-09-18 10:01:28 -0700
commit4de8efe1ef0810af492c161bfc1d3200958d75d8 (patch)
tree1b8d072127010f2dce6fc3b0e110d17f11a3fac7 /src
parent25fe164e19787ce9cfeb18390c72393575ac81ed (diff)
downloadtrackermap-server-4de8efe1ef0810af492c161bfc1d3200958d75d8.tar.gz
trackermap-server-4de8efe1ef0810af492c161bfc1d3200958d75d8.tar.bz2
trackermap-server-4de8efe1ef0810af492c161bfc1d3200958d75d8.zip
Refactor M-5000/10000 decoding
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/traccar/helper/NMEA.java126
-rw-r--r--src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java125
-rw-r--r--src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java4
3 files changed, 52 insertions, 203 deletions
diff --git a/src/main/java/org/traccar/helper/NMEA.java b/src/main/java/org/traccar/helper/NMEA.java
deleted file mode 100644
index cae47a8f6..000000000
--- a/src/main/java/org/traccar/helper/NMEA.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package org.traccar.helper;
-
-import java.util.HashMap;
-import java.util.Map;
-
-
-public class NMEA {
-
- // fucking java interfaces
- interface SentenceParser {
- public boolean parse(String[] tokens, GPSPosition position);
- }
-
- // utils
- static float Latitude2Decimal(String lat, String NS) {
- float med = Float.parseFloat(lat.substring(2)) / 60.0f;
- med += Float.parseFloat(lat.substring(0, 2));
- if (NS.startsWith("S")) {
- med = -med;
- }
- return med;
- }
-
- static float Longitude2Decimal(String lon, String WE) {
- float med = Float.parseFloat(lon.substring(3)) / 60.0f;
- med += Float.parseFloat(lon.substring(0, 3));
- if (WE.startsWith("W")) {
- med = -med;
- }
- return med;
- }
-
- // parsers
- class GPGGA implements SentenceParser {
- public boolean parse(String[] tokens, GPSPosition position) {
- position.time = Float.parseFloat(tokens[1]);
- position.lat = Latitude2Decimal(tokens[2], tokens[3]);
- position.lon = Longitude2Decimal(tokens[4], tokens[5]);
- position.quality = Integer.parseInt(tokens[6]);
- position.altitude = Float.parseFloat(tokens[9]);
- return true;
- }
- }
-
- class GPGGL implements SentenceParser {
- public boolean parse(String[] tokens, GPSPosition position) {
- position.lat = Latitude2Decimal(tokens[1], tokens[2]);
- position.lon = Longitude2Decimal(tokens[3], tokens[4]);
- position.time = Float.parseFloat(tokens[5]);
- return true;
- }
- }
-
- class GPRMC implements SentenceParser {
- public boolean parse(String[] tokens, GPSPosition position) {
- position.time = Float.parseFloat(tokens[1]);
- position.lat = Latitude2Decimal(tokens[3], tokens[4]);
- position.lon = Longitude2Decimal(tokens[5], tokens[6]);
- position.velocity = Float.parseFloat(tokens[7]);
- position.dir = Float.parseFloat(tokens[8]);
- return true;
- }
- }
-
- class GPVTG implements SentenceParser {
- public boolean parse(String[] tokens, GPSPosition position) {
- position.dir = Float.parseFloat(tokens[3]);
- return true;
- }
- }
-
- class GPRMZ implements SentenceParser {
- public boolean parse(String[] tokens, GPSPosition position) {
- position.altitude = Float.parseFloat(tokens[1]);
- return true;
- }
- }
-
- public class GPSPosition {
- public float time = 0.0f;
- public float lat = 0.0f;
- public float lon = 0.0f;
- public boolean fixed = false;
- public int quality = 0;
- public float dir = 0.0f;
- public float altitude = 0.0f;
- public float velocity = 0.0f;
-
- public void updatefix() {
- fixed = quality > 0;
- }
-
- public String toString() {
- return String.format("POSITION: lat: %f, lon: %f, time: %f, Q: %d, dir: %f, alt: %f, vel: %f", lat, lon, time, quality, dir, altitude, velocity);
- }
- }
-
- GPSPosition position = new GPSPosition();
-
- private static final Map<String, SentenceParser> sentenceParsers = new HashMap<String, SentenceParser>();
-
- public NMEA() {
- sentenceParsers.put("GPGGA", new GPGGA());
- sentenceParsers.put("GPGGL", new GPGGL());
- sentenceParsers.put("GPRMC", new GPRMC());
- sentenceParsers.put("GPRMZ", new GPRMZ());
- //only really good GPS devices have this sentence but ...
- sentenceParsers.put("GPVTG", new GPVTG());
- }
-
- public GPSPosition parse(String line) {
-
- if (line.startsWith("$")) {
- String nmea = line.substring(1);
- String[] tokens = nmea.split(",");
- String type = tokens[0];
- //TODO check crc
- if (sentenceParsers.containsKey(type)) {
- sentenceParsers.get(type).parse(tokens, position);
- }
- position.updatefix();
- }
-
- return position;
- }
-}
diff --git a/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java b/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java
index 6ca9b0795..34c879cb8 100644
--- a/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java
+++ b/src/main/java/org/traccar/protocol/PiligrimProtocolDecoder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2014 - 2020 Anton Tananaev (anton@traccar.org)
+ * Copyright 2014 - 2022 Anton Tananaev (anton@traccar.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -21,27 +21,23 @@ import io.netty.channel.Channel;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.QueryStringDecoder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.traccar.BaseHttpProtocolDecoder;
-import org.traccar.WebDataHandler;
-import org.traccar.session.DeviceSession;
import org.traccar.Protocol;
import org.traccar.helper.BitUtil;
import org.traccar.helper.DateBuilder;
-import org.traccar.helper.NMEA;
+import org.traccar.helper.Parser;
+import org.traccar.helper.PatternBuilder;
import org.traccar.model.Position;
+import org.traccar.session.DeviceSession;
import java.net.SocketAddress;
import java.nio.charset.StandardCharsets;
-import java.util.Date;
import java.util.LinkedList;
import java.util.List;
+import java.util.regex.Pattern;
public class PiligrimProtocolDecoder extends BaseHttpProtocolDecoder {
- private static final Logger LOGGER = LoggerFactory.getLogger(WebDataHandler.class);
-
public PiligrimProtocolDecoder(Protocol protocol) {
super(protocol);
}
@@ -54,6 +50,21 @@ public class PiligrimProtocolDecoder extends BaseHttpProtocolDecoder {
public static final int MSG_GPS_SENSORS = 0xF2;
public static final int MSG_EVENTS = 0xF3;
+ private static final Pattern PATTERN = new PatternBuilder()
+ .expression("[^$]+")
+ .text("$GPRMC,")
+ .number("(dd)(dd)(dd).d+,") // time (hhmmss)
+ .expression("([AV]),") // validity
+ .number("(dd)(dd.d+),") // latitude
+ .expression("([NS]),")
+ .number("(d{2,3})(dd.d+),") // longitude
+ .expression("([EW]),")
+ .number("(d+.d+),") // speed
+ .number("(d+.d+),") // course
+ .number("(dd)(dd)(dd),") // date (ddmmyy)
+ .any()
+ .compile();
+
@Override
protected Object decode(
Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
@@ -157,82 +168,42 @@ public class PiligrimProtocolDecoder extends BaseHttpProtocolDecoder {
}
return positions;
+
} else if (uri.startsWith("/push.do")) {
+
sendResponse(channel, "PUSH.DO: OK");
- /* Getting payload */
- ByteBuf contentStream = request.content();
- byte[] payloadBytes = new byte[Integer.parseInt(request.headers().get("Content-Length"))];
- contentStream.readBytes(payloadBytes);
- String payload = new String(payloadBytes);
-
- /* Payload structure:
- * &phone&message
- */
- String[] payloadParts = payload.split("&");
- /* LOGGER.debug("Payload parts: " + Arrays.toString(payloadParts)); */
- String phoneNumber = payloadParts[1].substring(15);
- DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, phoneNumber.substring(1));
+ String sentence = request.content().toString(StandardCharsets.US_ASCII);
+
+ String[] parts = sentence.split("&");
+ String phone = parts[1].substring(16);
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, phone);
if (deviceSession == null) {
return null;
}
- /* TODO: use keys for flags in 'positions'. */
- String message = payloadParts[2].substring(8).replaceFirst("[a-zA-Z! ]*; ", "");
- /* LOGGER.debug("Phone number: " + phoneNumber); */
- /* LOGGER.debug("Message: " + message); */
-
- if (message.startsWith("$GPRMC")) {
- /* Supported message structure:
- * GPS NMEA Command; GSM info; Unknown; Battery voltage?
- * Example: $GPRMC,180752.000,A,5314.0857,N,03421.8173,E,0.00,104.74,220722,,,A,V* 29,05; GSM: 250-01 0b54-0519,1c30,3e96,3ebe,412e 25; S; Batt: 405,M
- */
- LOGGER.debug("Supported message");
-
- String[] messageParts = message.split(";");
- /* LOGGER.debug("Message parts: " + Arrays.toString(messageParts)); */
-
- /* Parsing GPS */
- String unprocessedGpsCommand = messageParts[0];
-
- /* Getting rid of checksum */
- String gpsCommand = unprocessedGpsCommand.replaceFirst("A,V[*].*", "");
- /* LOGGER.debug("GPS command: " + gpsCommand); */
-
- NMEA gpsParser = new NMEA();
-
- NMEA.GPSPosition gpsPosition = gpsParser.parse(gpsCommand);
-
- /* LOGGER.debug("Time: " + gpsPosition.time); */
- /* LOGGER.debug("Coordinates: " + gpsPosition.lat + " " + gpsPosition.lon); */
- /* LOGGER.debug("Speed over ground: " + gpsPosition.velocity + " knots"); */
-
- /* Parsing other fields */
- /* String gsmInfo = messageParts[1]; */
- /* String unknown = messageParts[2]; */
- String batteryInfo = messageParts[messageParts.length - 1].substring(7).substring(0, 3);
- /* LOGGER.debug("Battery: " + batteryInfo); */
-
- /* Constructing response */
- Position position = new Position(getProtocolName());
-
- position.setDeviceId(deviceSession.getDeviceId());
- position.setValid(true);
- position.setLatitude(gpsPosition.lat);
- position.setLongitude(gpsPosition.lon);
- position.setTime(new Date(System.currentTimeMillis()));
- position.setSpeed(gpsPosition.velocity);
- position.setCourse(gpsPosition.dir);
- position.setAccuracy(gpsPosition.quality);
- position.setAltitude(gpsPosition.altitude);
- position.set(Position.KEY_BATTERY, Integer.parseInt(batteryInfo) / 100);
-
- LOGGER.debug("Supported message finish");
-
- return position;
- } else {
- LOGGER.error("Unsupported message");
+ Parser parser = new Parser(PATTERN, parts[2]);
+ if (!parser.matches()) {
+ return null;
}
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ DateBuilder dateBuilder = new DateBuilder()
+ .setTime(parser.nextInt(), parser.nextInt(), parser.nextInt());
+
+ position.setValid(parser.next().equals("A"));
+ position.setLatitude(parser.nextCoordinate());
+ position.setLongitude(parser.nextCoordinate());
+ position.setSpeed(parser.nextDouble());
+ position.setCourse(parser.nextDouble());
+
+ dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt());
+ position.setTime(dateBuilder.getDate());
+
+ return position;
+
}
return null;
diff --git a/src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java
index 475ac0125..0dd00462d 100644
--- a/src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java
+++ b/src/test/java/org/traccar/protocol/PiligrimProtocolDecoderTest.java
@@ -15,6 +15,10 @@ public class PiligrimProtocolDecoderTest extends ProtocolTest {
"/bingps?imei=868204005544720&csq=18&vout=00&vin=4050&dataid=00000000",
binary("fff2200d4110061a32354f3422310062000a0005173b0000a101000300005e00fff2200d4110100932354f2b22310042000b000e173b00009f01000700006000")));
+ verifyPosition(decoder, request(HttpMethod.POST,
+ "/push.do",
+ buffer("&phoneNumber=%2B+78000000000&message=ALARM KEY; $GPRMC,180752.000,A,5314.0857,N,03421.8173,E,0.00,104.74,220722,,,A,V* 29,05; GSM: 250-01 0b54-0519,1c30,3e96,3ebe,412e 25; S; Batt: 405,M")));
+
}
}