aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Tananaev <anton.tananaev@gmail.com>2012-11-13 21:58:17 +1300
committerAnton Tananaev <anton.tananaev@gmail.com>2012-11-13 21:58:17 +1300
commit3ee4d2fba538eee4d1774bd79e07c64dc0af97e5 (patch)
treeaaf69aa6b63874ccb226f966b2681746eee28a65
parentf0d4f9de581b1f579608cbc3f5165c0b14317993 (diff)
downloadtrackermap-server-3ee4d2fba538eee4d1774bd79e07c64dc0af97e5.tar.gz
trackermap-server-3ee4d2fba538eee4d1774bd79e07c64dc0af97e5.tar.bz2
trackermap-server-3ee4d2fba538eee4d1774bd79e07c64dc0af97e5.zip
Added TR20 support (Fix #79)
-rw-r--r--default.cfg4
-rw-r--r--src/org/traccar/Server.java27
-rw-r--r--src/org/traccar/protocol/Tr20ProtocolDecoder.java142
-rwxr-xr-xtest.sh3
-rw-r--r--test/org/traccar/protocol/Tr20ProtocolDecoderTest.java21
5 files changed, 197 insertions, 0 deletions
diff --git a/default.cfg b/default.cfg
index c8186a358..8934d93df 100644
--- a/default.cfg
+++ b/default.cfg
@@ -164,4 +164,8 @@
<entry key="pt502.enable">true</entry>
<entry key="pt502.port">5017</entry>
+ <!-- TR20 server configuration -->
+ <entry key="tr20.enable">true</entry>
+ <entry key="tr20.port">5018</entry>
+
</properties>
diff --git a/src/org/traccar/Server.java b/src/org/traccar/Server.java
index 051d040b9..38f0a1388 100644
--- a/src/org/traccar/Server.java
+++ b/src/org/traccar/Server.java
@@ -104,6 +104,7 @@ public class Server {
initEv603Server(properties);
initV680Server(properties);
initPt502Server(properties);
+ initTr20Server(properties);
// Initialize web server
if (Boolean.valueOf(properties.getProperty("http.enable"))) {
@@ -652,4 +653,30 @@ public class Server {
serverList.add(server);
}
}
+
+ /**
+ * Init TR20 server
+ */
+ private void initTr20Server(Properties properties) throws SQLException {
+
+ String protocol = "tr20";
+ if (isProtocolEnabled(properties, protocol)) {
+
+ TrackerServer server = new TrackerServer(getProtocolPort(properties, protocol));
+ final Integer resetDelay = getProtocolResetDelay(properties, protocol);
+
+ server.setPipelineFactory(new GenericPipelineFactory(server, dataManager, isLoggerEnabled(), resetDelay, geocoder) {
+ protected void addSpecificHandlers(ChannelPipeline pipeline) {
+ byte delimiter[] = { (byte) '\r', (byte) '\n' };
+ pipeline.addLast("frameDecoder",
+ new DelimiterBasedFrameDecoder(1024, ChannelBuffers.wrappedBuffer(delimiter)));
+ pipeline.addLast("stringDecoder", new StringDecoder());
+ pipeline.addLast("stringEncoder", new StringEncoder());
+ pipeline.addLast("objectDecoder", new Tr20ProtocolDecoder(getDataManager()));
+ }
+ });
+
+ serverList.add(server);
+ }
+ }
}
diff --git a/src/org/traccar/protocol/Tr20ProtocolDecoder.java b/src/org/traccar/protocol/Tr20ProtocolDecoder.java
new file mode 100644
index 000000000..8f2f49218
--- /dev/null
+++ b/src/org/traccar/protocol/Tr20ProtocolDecoder.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2012 Anton Tananaev (anton.tananaev@gmail.com)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.traccar.protocol;
+
+import java.util.Calendar;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.traccar.GenericProtocolDecoder;
+import org.traccar.model.DataManager;
+import org.traccar.model.Position;
+
+/**
+ * TR20 tracker protocol decoder
+ */
+public class Tr20ProtocolDecoder extends GenericProtocolDecoder {
+
+ /**
+ * Initialize
+ */
+ public Tr20ProtocolDecoder(DataManager dataManager) {
+ super(dataManager);
+ }
+
+ static private Pattern patternPing = Pattern.compile(
+ "\\%\\%[^,]+,(\\d+)");
+
+ //%%TR-10,A,050916070549,N2240.8887E11359.2994,0,000,NA,D3800000,150,CFG:resend|
+ //%%123456789012345,A,120101121800,N6000.0000E13000.0000,0,000,0,01034802,150,[Message]
+ static private Pattern patternData = Pattern.compile(
+ "\\%\\%" +
+ "([^,]+)," + // Id
+ "([AL])," + // Validity
+ "(\\d{2})(\\d{2})(\\d{2})" + // Date (YYMMDD)
+ "(\\d{2})(\\d{2})(\\d{2})," + // Time (HHMMSS)
+ "([NS])" +
+ "(\\d{2})(\\d{2}\\.\\d+)" + // Latitude (DDMM.MMMM)
+ "([EW])" +
+ "(\\d{3})(\\d{2}\\.\\d+)," + // Longitude (DDDMM.MMMM)
+ "(\\d+)," + // Speed
+ "(\\d+)," + // Course
+ ".*");
+
+ /**
+ * Decode message
+ */
+ protected Object decode(
+ ChannelHandlerContext ctx, Channel channel, Object msg)
+ throws Exception {
+
+ String sentence = (String) msg;
+
+ // Keep alive message
+ Matcher parser = patternPing.matcher(sentence);
+ if (parser.matches()) {
+
+ // Send response
+ if (channel != null) {
+ channel.write("&&" + parser.group(1) + "\r\n");
+ }
+ } else {
+
+ // Data message parse
+ parser = patternData.matcher(sentence);
+
+ // Unknown message
+ if (!parser.matches()) {
+ return null;
+ }
+
+ // Create new position
+ Position position = new Position();
+ StringBuilder extendedInfo = new StringBuilder("<protocol>tr20</protocol>");
+
+ Integer index = 1;
+
+ // Get device by id
+ String id = parser.group(index++);
+ position.setDeviceId(getDataManager().getDeviceByImei(id).getId());
+
+ // Validity
+ position.setValid(parser.group(index++).compareTo("A") == 0 ? true : false);
+
+ // Time
+ Calendar time = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
+ time.clear();
+ time.set(Calendar.YEAR, 2000 + Integer.parseInt(parser.group(index++)));
+ time.set(Calendar.MONTH, Integer.parseInt(parser.group(index++)) - 1);
+ time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(parser.group(index++)));
+ time.set(Calendar.HOUR, Integer.parseInt(parser.group(index++)));
+ time.set(Calendar.MINUTE, Integer.parseInt(parser.group(index++)));
+ time.set(Calendar.SECOND, Integer.parseInt(parser.group(index++)));
+ position.setTime(time.getTime());
+
+ // Latitude
+ int hemisphere = 1;
+ if (parser.group(index++).compareTo("S") == 0) hemisphere = -1;
+ Double latitude = Double.valueOf(parser.group(index++));
+ latitude += Double.valueOf(parser.group(index++)) / 60;
+ position.setLatitude(latitude * hemisphere);
+
+ // Longitude
+ hemisphere = 1;
+ if (parser.group(index++).compareTo("W") == 0) hemisphere = -1;
+ Double lonlitude = Double.valueOf(parser.group(index++));
+ lonlitude += Double.valueOf(parser.group(index++)) / 60;
+ position.setLongitude(lonlitude * hemisphere);
+
+ // Speed
+ position.setSpeed(Double.valueOf(parser.group(index++)));
+
+ // Course
+ position.setCourse(Double.valueOf(parser.group(index++)));
+
+ // Altitude
+ position.setAltitude(0.0);
+
+ // Extended info
+ position.setExtendedInfo(extendedInfo.toString());
+
+ return position;
+ }
+
+ return null;
+ }
+
+}
diff --git a/test.sh b/test.sh
index 8e25e10b8..73eadbd75 100755
--- a/test.sh
+++ b/test.sh
@@ -62,3 +62,6 @@ echo "16. v680"
echo "17. pt502"
(echo -n -e "\$POS,123456,121700.000,A,6000.0000,N,13000.0000,E,0.0,0.0,010112,,,A/00000,00000/0/23895000//\r\n";) | nc -v localhost 5017
+
+echo "18. tr20"
+(echo -n -e "%%123456789012345,A,120101121800,N6000.0000E13000.0000,0,000,0,01034802,150,[Message]\r\n";) | nc -v localhost 5018
diff --git a/test/org/traccar/protocol/Tr20ProtocolDecoderTest.java b/test/org/traccar/protocol/Tr20ProtocolDecoderTest.java
new file mode 100644
index 000000000..aa978655b
--- /dev/null
+++ b/test/org/traccar/protocol/Tr20ProtocolDecoderTest.java
@@ -0,0 +1,21 @@
+package org.traccar.protocol;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import org.junit.Test;
+
+public class Tr20ProtocolDecoderTest {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ Tr20ProtocolDecoder decoder = new Tr20ProtocolDecoder(new TestDataManager());
+
+ assertNull(decoder.decode(null, null, "%%TRACKPRO01,1"));
+
+ assertNotNull(decoder.decode(null, null,
+ "%%TR-10,A,050916070549,N2240.8887E11359.2994,0,000,NA,D3800000,150,CFG:resend|"));
+
+ }
+
+}