From a6b992410f828da7d36284a5f005617f50723b1b Mon Sep 17 00:00:00 2001 From: Geodelta <67260714+geodelta@users.noreply.github.com> Date: Tue, 30 Jun 2020 16:57:27 +0200 Subject: Implement Mictrack Low Altitude Flight Decoder (#4546) * Implement Mictrack Low Altitude Flight Decoder * Fix headers * Add MictrackLowAltitudeFlightProtocolDecoderTest test for position * Merge Mictrack and Mictrack Low Altitude Flight decoders * Remove empty line * Minor style changes based on code review * Cast msg Object to String once in MictrackProtocolDecoder Co-authored-by: Roeland Boeters --- .../traccar/protocol/MictrackProtocolDecoder.java | 74 +++++++++++++++++++++- .../protocol/MictrackProtocolDecoderTest.java | 17 ++++- 2 files changed, 89 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java b/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java index a2fccb707..0f815ca7b 100644 --- a/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java +++ b/src/main/java/org/traccar/protocol/MictrackProtocolDecoder.java @@ -1,5 +1,6 @@ /* * Copyright 2019 Anton Tananaev (anton@traccar.org) + * Copyright 2020 Roeland Boeters (roeland@geodelta.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +20,9 @@ import io.netty.channel.Channel; import org.traccar.BaseProtocolDecoder; import org.traccar.DeviceSession; import org.traccar.Protocol; +import org.traccar.helper.DateBuilder; +import org.traccar.helper.Parser; +import org.traccar.helper.PatternBuilder; import org.traccar.helper.UnitsConverter; import org.traccar.model.CellTower; import org.traccar.model.Network; @@ -30,7 +34,10 @@ import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.LinkedList; +import java.util.List; import java.util.TimeZone; +import java.util.regex.Pattern; public class MictrackProtocolDecoder extends BaseProtocolDecoder { @@ -38,6 +45,19 @@ public class MictrackProtocolDecoder extends BaseProtocolDecoder { super(protocol); } + private static final Pattern PATTERN_LOW_ALTITUDE = new PatternBuilder() + .number("(dd)(dd)(dd).d+,") // time (hhmmss.sss) + .expression("([AV]),") // validity + .number("(d+)(dd.d+),") // latitude + .expression("([NS]),") + .number("(d+)(dd.d+),") // longitude + .expression("([EW]),") + .number("(d+.?d*)?,") // speed + .number("(d+.?d*)?,") // course + .number("(d+.?d*)?,") // altitude + .number("(dd)(dd)(dd)") // date (ddmmyy) + .compile(); + private Date decodeTime(String data) throws ParseException { DateFormat dateFormat = new SimpleDateFormat("yyMMddHHmmss"); dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -142,8 +162,18 @@ public class MictrackProtocolDecoder extends BaseProtocolDecoder { @Override protected Object decode( Channel channel, SocketAddress remoteAddress, Object msg) throws Exception { + String sentence = ((String) msg).trim(); + + if (sentence.startsWith("MT")) { + return decodeStandard(channel, remoteAddress, sentence); + } else { + return decodeLowAltitude(channel, remoteAddress, sentence); + } + } - String[] fragments = ((String) msg).split(";"); + private Object decodeStandard( + Channel channel, SocketAddress remoteAddress, String sentence) throws Exception { + String[] fragments = sentence.split(";"); DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, fragments[2]); if (deviceSession == null) { @@ -178,4 +208,46 @@ public class MictrackProtocolDecoder extends BaseProtocolDecoder { return position; } + private Object decodeLowAltitude( + Channel channel, SocketAddress remoteAddress, String sentence) throws Exception { + String deviceId = sentence.substring(0, sentence.indexOf("$")); + + DeviceSession deviceSession = getDeviceSession(channel, remoteAddress, deviceId); + if (deviceSession == null) { + return null; + } + + String[] fragments = sentence.substring(sentence.indexOf("$")).split("\\$"); + + List positions = new LinkedList<>(); + + for (String message : fragments) { + Parser parser = new Parser(PATTERN_LOW_ALTITUDE, message); + + if (parser.matches()) { + + 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(0)); + position.setCourse(parser.nextDouble(0)); + position.setAltitude(parser.nextDouble(0)); + + dateBuilder.setDateReverse(parser.nextInt(), parser.nextInt(), parser.nextInt()); + position.setTime(dateBuilder.getDate()); + + positions.add(position); + } + } + + return positions; + } + } diff --git a/src/test/java/org/traccar/protocol/MictrackProtocolDecoderTest.java b/src/test/java/org/traccar/protocol/MictrackProtocolDecoderTest.java index 794b2b57e..605a02b92 100644 --- a/src/test/java/org/traccar/protocol/MictrackProtocolDecoderTest.java +++ b/src/test/java/org/traccar/protocol/MictrackProtocolDecoderTest.java @@ -6,7 +6,7 @@ import org.traccar.ProtocolTest; public class MictrackProtocolDecoderTest extends ProtocolTest { @Test - public void testDecode() throws Exception { + public void testDecodeStandard() throws Exception { MictrackProtocolDecoder decoder = new MictrackProtocolDecoder(null); @@ -31,7 +31,22 @@ public class MictrackProtocolDecoderTest extends ProtocolTest { verifyAttributes(decoder, text( "MT;5;866425031379169;RH;5+190116112648+0+0+0+0+11+3954+1")); + } + + @Test + public void testDecodeLowAltitude() throws Exception { + + MictrackProtocolDecoder decoder = new MictrackProtocolDecoder(null); + + verifyPositions(decoder, text( + "861108032038761$062232.00,A,2238.2832,N,11401.7381,E,0.01,309.62,95.0,131117")); + + verifyPositions(decoder, text( + "861108032038761$062232.00,A,2238.2832,N,11401.7381,E,0.01,309.62,95.0,131117$062332.00,A,2238.2836,N,11401.7386,E,0.06,209.62,95.0,131117")); + verifyPositions(decoder, text( + "861108032038761$062232.00,A,2238.2832,N,11401.7381,E,0.01,309.62,95.0,131117"), + position("2017-11-13 06:22:32.000", true, 22.63806, 114.028976)); } } -- cgit v1.2.3