aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/org/traccar/protocol/AdmProtocolDecoder.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/traccar/protocol/AdmProtocolDecoder.java')
-rw-r--r--src/main/java/org/traccar/protocol/AdmProtocolDecoder.java198
1 files changed, 198 insertions, 0 deletions
diff --git a/src/main/java/org/traccar/protocol/AdmProtocolDecoder.java b/src/main/java/org/traccar/protocol/AdmProtocolDecoder.java
new file mode 100644
index 000000000..52d1439ed
--- /dev/null
+++ b/src/main/java/org/traccar/protocol/AdmProtocolDecoder.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012 - 2018 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 io.netty.buffer.ByteBuf;
+import io.netty.channel.Channel;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.DeviceSession;
+import org.traccar.Protocol;
+import org.traccar.helper.BitUtil;
+import org.traccar.helper.UnitsConverter;
+import org.traccar.model.Position;
+
+import java.net.SocketAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Date;
+
+public class AdmProtocolDecoder extends BaseProtocolDecoder {
+
+ public AdmProtocolDecoder(Protocol protocol) {
+ super(protocol);
+ }
+
+ public static final int CMD_RESPONSE_SIZE = 0x84;
+ public static final int MSG_IMEI = 0x03;
+ public static final int MSG_PHOTO = 0x0A;
+ public static final int MSG_ADM5 = 0x01;
+
+ private Position decodeData(Channel channel, SocketAddress remoteAddress, ByteBuf buf, int type) {
+
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ if (BitUtil.to(type, 2) == 0) {
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ position.set(Position.KEY_VERSION_FW, buf.readUnsignedByte());
+ position.set(Position.KEY_INDEX, buf.readUnsignedShortLE());
+
+ int status = buf.readUnsignedShortLE();
+ position.set(Position.KEY_STATUS, status);
+ position.setValid(!BitUtil.check(status, 5));
+ position.setLatitude(buf.readFloatLE());
+ position.setLongitude(buf.readFloatLE());
+ position.setCourse(buf.readUnsignedShortLE() * 0.1);
+ position.setSpeed(UnitsConverter.knotsFromKph(buf.readUnsignedShortLE() * 0.1));
+
+ position.set(Position.KEY_ACCELERATION, buf.readUnsignedByte() * 0.1);
+ position.setAltitude(buf.readShortLE());
+ position.set(Position.KEY_HDOP, buf.readUnsignedByte() * 0.1);
+ position.set(Position.KEY_SATELLITES, buf.readUnsignedByte() & 0x0f);
+
+ position.setTime(new Date(buf.readUnsignedIntLE() * 1000));
+
+ position.set(Position.KEY_POWER, buf.readUnsignedShortLE() * 0.001);
+ position.set(Position.KEY_BATTERY, buf.readUnsignedShortLE() * 0.001);
+
+ if (BitUtil.check(type, 2)) {
+ buf.readUnsignedByte(); // vib
+ buf.readUnsignedByte(); // vib_count
+
+ int out = buf.readUnsignedByte();
+ for (int i = 0; i <= 3; i++) {
+ position.set(Position.PREFIX_OUT + (i + 1), BitUtil.check(out, i) ? 1 : 0);
+ }
+
+ buf.readUnsignedByte(); // in_alarm
+ }
+
+ if (BitUtil.check(type, 3)) {
+ for (int i = 1; i <= 6; i++) {
+ position.set(Position.PREFIX_ADC + i, buf.readUnsignedShortLE() * 0.001);
+ }
+ }
+
+ if (BitUtil.check(type, 4)) {
+ for (int i = 1; i <= 2; i++) {
+ position.set(Position.PREFIX_COUNT + i, buf.readUnsignedIntLE());
+ }
+ }
+
+ if (BitUtil.check(type, 5)) {
+ for (int i = 1; i <= 3; i++) {
+ buf.readUnsignedShortLE(); // fuel level
+ }
+ for (int i = 1; i <= 3; i++) {
+ position.set(Position.PREFIX_TEMP + i, buf.readUnsignedByte());
+ }
+ }
+
+ if (BitUtil.check(type, 6)) {
+ int endIndex = buf.readerIndex() + buf.readUnsignedByte();
+ while (buf.readerIndex() < endIndex) {
+ int mask = buf.readUnsignedByte();
+ long value;
+ switch (BitUtil.from(mask, 6)) {
+ case 3:
+ value = buf.readLongLE();
+ break;
+ case 2:
+ value = buf.readUnsignedIntLE();
+ break;
+ case 1:
+ value = buf.readUnsignedShortLE();
+ break;
+ default:
+ value = buf.readUnsignedByte();
+ break;
+ }
+ int index = BitUtil.to(mask, 6);
+ switch (index) {
+ case 1:
+ position.set(Position.PREFIX_TEMP + 1, value);
+ break;
+ case 2:
+ position.set("humidity", value);
+ break;
+ case 3:
+ position.set("illumination", value);
+ break;
+ case 4:
+ position.set(Position.KEY_BATTERY, value);
+ break;
+ default:
+ position.set("can" + index, value);
+ break;
+ }
+ }
+ }
+
+ if (BitUtil.check(type, 7)) {
+ position.set(Position.KEY_ODOMETER, buf.readUnsignedIntLE());
+ }
+
+ return position;
+ }
+
+ return null;
+ }
+
+ private Position parseCommandResponse(Channel channel, SocketAddress remoteAddress, ByteBuf buf) {
+ DeviceSession deviceSession = getDeviceSession(channel, remoteAddress);
+ if (deviceSession == null) {
+ return null;
+ }
+
+ Position position = new Position(getProtocolName());
+ position.setDeviceId(deviceSession.getDeviceId());
+
+ getLastLocation(position, null);
+
+ int responseTextLength = buf.bytesBefore((byte) 0);
+ if (responseTextLength < 0) {
+ responseTextLength = CMD_RESPONSE_SIZE - 3;
+ }
+ position.set(Position.KEY_RESULT, buf.readSlice(responseTextLength).toString(StandardCharsets.UTF_8));
+
+ return position;
+ }
+
+ @Override
+ protected Object decode(Channel channel, SocketAddress remoteAddress, Object msg) throws Exception {
+ ByteBuf buf = (ByteBuf) msg;
+
+ buf.readUnsignedShortLE(); // device id
+
+ int size = buf.readUnsignedByte();
+ if (size != CMD_RESPONSE_SIZE) {
+ int type = buf.readUnsignedByte();
+ if (type == MSG_IMEI) {
+ getDeviceSession(channel, remoteAddress, buf.readSlice(15).toString(StandardCharsets.UTF_8));
+ } else {
+ return decodeData(channel, remoteAddress, buf, type);
+ }
+ } else {
+ return parseCommandResponse(channel, remoteAddress, buf);
+ }
+
+ return null;
+ }
+
+}