aboutsummaryrefslogtreecommitdiff
path: root/src/org/traccar/protocol/At2000ProtocolDecoder.java
diff options
context:
space:
mode:
authorPhilipp Prangenberg <philipp.prangenberg@derkurier.de>2016-12-05 12:03:08 +0100
committerPhilipp Prangenberg <philipp.prangenberg@derkurier.de>2016-12-05 12:03:08 +0100
commita21f436a58133f7da0cae06366d729665f3b8f9c (patch)
tree72ff1743d96f79e4a9d85b0d48715e5f9aa67cf9 /src/org/traccar/protocol/At2000ProtocolDecoder.java
parent960bf899414d89221e92138fdb98777c3f4f73ec (diff)
parent40607036c5aa6385a7ae3f3a283bf107238a5944 (diff)
downloadtrackermap-server-a21f436a58133f7da0cae06366d729665f3b8f9c.tar.gz
trackermap-server-a21f436a58133f7da0cae06366d729665f3b8f9c.tar.bz2
trackermap-server-a21f436a58133f7da0cae06366d729665f3b8f9c.zip
Merge remote-tracking branch 'upstream/master'
Diffstat (limited to 'src/org/traccar/protocol/At2000ProtocolDecoder.java')
-rw-r--r--src/org/traccar/protocol/At2000ProtocolDecoder.java134
1 files changed, 134 insertions, 0 deletions
diff --git a/src/org/traccar/protocol/At2000ProtocolDecoder.java b/src/org/traccar/protocol/At2000ProtocolDecoder.java
new file mode 100644
index 000000000..17da0eef7
--- /dev/null
+++ b/src/org/traccar/protocol/At2000ProtocolDecoder.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2016 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.
+ * 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 org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import javax.xml.bind.DatatypeConverter;
+import java.net.SocketAddress;
+import java.nio.ByteOrder;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+
+public class At2000ProtocolDecoder extends BaseProtocolDecoder {
+
+ private static final int BLOCK_LENGTH = 16;
+
+ public At2000ProtocolDecoder(At2000Protocol protocol) {
+ super(protocol);
+ }
+
+ public static final int MSG_ACKNOWLEDGEMENT = 0x00;
+ public static final int MSG_DEVICE_ID = 0x01;
+ public static final int MSG_TRACK_REQUEST = 0x88;
+ public static final int MSG_TRACK_RESPONSE = 0x89;
+ public static final int MSG_SESSION_END = 0x0c;
+
+ private Cipher cipher;
+
+ private static void sendResponse(Channel channel) {
+ if (channel != null) {
+ ChannelBuffer response = ChannelBuffers.directBuffer(BLOCK_LENGTH);
+ response.writeByte(MSG_ACKNOWLEDGEMENT);
+ response.writeMedium(1);
+ response.writeByte(0x00); // success
+ response.writerIndex(BLOCK_LENGTH);
+ channel.write(response);
+ }
+ }
+
+ @Override
+ protected Object decode(
+ Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+
+ ChannelBuffer buf = (ChannelBuffer) msg;
+
+ if (buf.getUnsignedByte(buf.readerIndex()) == 0x01) {
+ buf.readUnsignedByte(); // codec id
+ }
+
+ int type = buf.readUnsignedByte();
+ buf.readUnsignedMedium(); // length
+ buf.skipBytes(BLOCK_LENGTH - 1 - 3);
+
+ if (type == MSG_DEVICE_ID) {
+
+ String imei = buf.readBytes(15).toString(StandardCharsets.US_ASCII);
+ if (getDeviceSession(channel, remoteAddress, imei) != null) {
+
+ byte[] iv = new byte[BLOCK_LENGTH];
+ buf.readBytes(iv);
+ IvParameterSpec ivSpec = new IvParameterSpec(iv);
+
+ SecretKeySpec keySpec = new SecretKeySpec(
+ DatatypeConverter.parseHexBinary("000102030405060708090a0b0c0d0e0f"), "AES");
+
+ cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
+
+ byte[] data = new byte[BLOCK_LENGTH];
+ buf.readBytes(data);
+ cipher.update(data);
+
+ }
+
+ } else if (type == MSG_TRACK_RESPONSE) {
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position();
+ position.setProtocol(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ byte[] data = new byte[buf.capacity() - BLOCK_LENGTH];
+ buf.readBytes(data);
+ buf = ChannelBuffers.wrappedBuffer(ByteOrder.LITTLE_ENDIAN, cipher.update(data));
+
+ buf.readUnsignedShort(); // index
+ buf.readUnsignedShort(); // reserved
+
+ position.setValid(true);
+
+ position.setTime(new Date(buf.readLong() * 1000));
+
+ position.setLatitude(buf.readFloat());
+ position.setLongitude(buf.readFloat());
+ position.setAltitude(buf.readFloat());
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readFloat()));
+ position.setCourse(buf.readFloat());
+
+ return position;
+
+ }
+
+ sendResponse(channel);
+
+ return null;
+ }
+
+}