aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/org/traccar/protocol/T800XProtocolDecoder.java288
-rw-r--r--test/org/traccar/protocol/T800XProtocolDecoderTest.java32
2 files changed, 320 insertions, 0 deletions
diff --git a/src/org/traccar/protocol/T800XProtocolDecoder.java b/src/org/traccar/protocol/T800XProtocolDecoder.java
new file mode 100644
index 000000000..aff8d013a
--- /dev/null
+++ b/src/org/traccar/protocol/T800XProtocolDecoder.java
@@ -0,0 +1,288 @@
+package org.traccar.protocol;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.jboss.netty.channel.Channel;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.traccar.BaseProtocolDecoder;
+import org.traccar.database.DataManager;
+import org.traccar.helper.ChannelBufferTools;
+import org.traccar.helper.Log;
+import org.traccar.model.ExtendedInfoFormatter;
+import org.traccar.model.Position;
+import org.traccar.model.Status;
+
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+ * Created by Ankit on 21-10-2015.
+ */
+
+
+public class T800XProtocolDecoder extends BaseProtocolDecoder {
+
+ public T800XProtocolDecoder(DataManager dataManager, String protocol, Properties properties) {
+ super(dataManager, protocol, properties);
+ }
+
+ private final TimeZone timeZone = TimeZone.getTimeZone("UTC");
+ SimpleDateFormat dateFormatGmt = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
+ SimpleDateFormat dateFormatLocal = new SimpleDateFormat("yyyy-MMM-dd HH:mm:ss");
+
+ private String readImei(ChannelBuffer buf) {
+ int b = buf.readUnsignedByte();
+ StringBuilder imei = new StringBuilder();
+ imei.append(b & 0x0F);
+ for (int i = 0; i < 7; i++) {
+ b = buf.readUnsignedByte();
+ imei.append((b & 0xF0) >> 4);
+ imei.append(b & 0x0F);
+ }
+ return imei.toString();
+ }
+
+ private static final int MSG_LOGIN = 0x01;
+ private static final int MSG_GPS = 0x02;
+ private static final int MSG_HEARTBEAT = 0x03;
+ private static final int MSG_ALARM = 0x04;
+ private static final int MSG_STATE = 0x05;
+ private static final int MSG_SMS = 0x06;
+ private static final int MSG_OBD = 0x07;
+ private static final int MSG_INTERACTIVE = 0x80;
+ private static final int MSG_DATA = 0x81;
+
+ private Long deviceId;
+
+ private void sendResponse(Channel channel, int type, int index, String imei) {
+ if (channel != null) {
+ ChannelBuffer response = ChannelBuffers.buffer(7+imei.getBytes().length);
+ response.writeByte(0x23);
+ response.writeByte(0x23); // header
+ response.writeByte(type);
+ response.writeByte(0x00);
+ response.writeByte(0x0F); // length
+ response.writeByte(0x00);
+ response.writeByte(0x01); //index
+ //IMEI
+ response.writeBytes(ChannelBufferTools.convertHexString("0" + imei));
+ channel.write(response);
+ }
+ }
+
+ @Override
+ protected Object decode(
+ ChannelHandlerContext ctx, Channel channel, Object msg)
+ throws Exception {
+
+
+ ChannelBuffer buf = (ChannelBuffer) msg;
+
+ List<Position> positions=new ArrayList<Position>();
+ int i=0;
+ while (buf.readable()){
+ i++;
+ buf.skipBytes(2); // header
+ int type = buf.readUnsignedByte(); // type
+ buf.readShort(); // length
+ int index = buf.readUnsignedShort(); // index
+ String imei = ChannelBufferTools.readHexString(buf, 16).substring(1); // imei
+
+ if (type == MSG_LOGIN) {
+ try {
+ deviceId = getDataManager().getDeviceByImei(imei).getId();
+ sendResponse(channel, type, index, imei); // send login response
+ return null;
+ } catch (Exception error) {
+ Log.warning("Unknown device - " + imei);
+ }
+ } else if (deviceId != null &&
+ (type == MSG_GPS || type == MSG_ALARM)) {
+
+ ExtendedInfoFormatter extendedInfo = new ExtendedInfoFormatter(getProtocol());
+ extendedInfo.set("index", index);
+
+ //ACC ON Interval TODO
+ buf.skipBytes(2);
+ //Acc OFF Interval TODO
+ buf.skipBytes(2);
+
+ //Angel Degree TODO
+ buf.skipBytes(1);
+
+ //Angel Distance TODO
+ buf.skipBytes(2);
+
+ //Speed Alarm TODO
+ buf.skipBytes(2);
+
+ //GPS Status TODO
+ String locationType = getBits(buf.readUnsignedByte());
+
+ //Gsensor Manager TODO
+ buf.skipBytes(1);
+
+
+ //Reserve Bit
+ buf.skipBytes(1);
+
+ //HeartBit
+ buf.skipBytes(1);
+
+ //Relay Status
+ buf.skipBytes(1);
+
+ //Drag Alarm Setting
+ buf.skipBytes(2);
+
+ // Digital I/O Status
+ String binaryDigitalIO = getBits(buf.readUnsignedShort());
+ extendedInfo.set("acc", binaryDigitalIO.charAt(1));
+ extendedInfo.set("ac", binaryDigitalIO.charAt(2));
+
+ // 2 Analog Input
+ buf.skipBytes(4);
+
+ // Alarm Data
+ String alarmData = ChannelBufferTools.readHexString(buf, 2);
+ String statusType=getStatusType(alarmData);
+ extendedInfo.set(statusType,true);
+ if(type == MSG_ALARM)
+ {
+ Log.debug("ALARM"+statusType);
+ sendResponse(channel,type,index,imei+alarmData);
+ }
+
+ // Reserve
+ buf.skipBytes(1);
+
+ // Mileage
+ buf.skipBytes(4);
+
+
+ // Inner Battery Voltage
+ double batteryVoltage = Double.parseDouble(ChannelBufferTools.readHexString(buf, 2));
+ extendedInfo.set("power", getBatteryPerc(batteryVoltage));
+
+ // Time & Date Calculation
+ Calendar time = Calendar.getInstance();
+ time.clear();
+ time.set(Calendar.YEAR, 2000 + Integer.parseInt(ChannelBufferTools.readHexString(buf, 2)));
+ time.set(Calendar.MONTH, (Integer.parseInt(ChannelBufferTools.readHexString(buf, 2)) - 1));
+ time.set(Calendar.DAY_OF_MONTH, Integer.parseInt(ChannelBufferTools.readHexString(buf, 2)));
+ time.set(Calendar.HOUR_OF_DAY, Integer.parseInt(ChannelBufferTools.readHexString(buf, 2)));
+ time.set(Calendar.MINUTE, Integer.parseInt(ChannelBufferTools.readHexString(buf, 2)));
+ time.set(Calendar.SECOND, Integer.parseInt(ChannelBufferTools.readHexString(buf, 2)));
+
+ if (locationType.charAt(1) == '1') {
+ Log.debug("GPS DATA");
+ Position position = new Position();
+ position.setDeviceId(deviceId);
+ position.setTime(time.getTime());
+
+ // Read Altitude
+ byte[] altitude = new byte[]{buf.readByte(), buf.readByte(), buf.readByte(), buf.readByte()};
+ position.setAltitude((double) bytes2Float(altitude, 0));
+
+ // Read Longitude & Latitude
+ byte[] longitude = new byte[]{buf.readByte(), buf.readByte(), buf.readByte(), buf.readByte()};
+ byte[] latitude = new byte[]{buf.readByte(), buf.readByte(), buf.readByte(), buf.readByte()};
+ position.setLongitude((double) bytes2Float(longitude, 0));
+ position.setLatitude((double) bytes2Float(latitude, 0));
+
+ // Read Speed
+ String str_speed = ChannelBufferTools.readHexString(buf, 4);
+ String result = str_speed.substring(0, 3) + "." + str_speed.substring(3);
+ position.setSpeed(Double.parseDouble(result) * 0.539957);
+
+ position.setExtendedInfo(extendedInfo.toString());
+ positions.add(position);
+
+ buf.skipBytes(2);
+ }
+ else {
+ Log.debug("LBS DATA");
+ if(type == MSG_ALARM)
+ {
+ Status status = new Status();
+ status.setDate(time.getTime());
+ status.setDeviceid(deviceId);
+ status.setStatusType(statusType);
+
+ return status;
+ }
+ buf.skipBytes(16);
+ }
+ } else if (deviceId != null &&
+ (type == MSG_HEARTBEAT)) {
+ dateFormatGmt.setTimeZone(TimeZone.getTimeZone("GMT"));
+ Status status = new Status();
+ status.setDate(dateFormatLocal.parse(dateFormatGmt.format(new Date())));
+ status.setDeviceid(deviceId);
+ sendResponse(channel, type, index, imei);
+ return status;
+ }
+ }
+
+ return positions;
+ }
+
+
+ private static String getBits(int flags) {
+ int hexFlag = Integer.parseInt(Integer.toHexString(flags), 16);
+ String binaryAlarm = Integer.toBinaryString(hexFlag);
+ binaryAlarm = (String.format("%8s", binaryAlarm)).replace(' ', '0');
+ return binaryAlarm;
+ }
+
+ public static float bytes2Float(byte[] bytes, int offset) {
+ int value;
+ value = bytes[offset];
+ value &= 0xff;
+ value |= ((long) bytes[offset + 1] << 8);
+ value &= 0xffff;
+ value |= ((long) bytes[offset + 2] << 16);
+ value &= 0xffffff;
+ value |= ((long) bytes[offset + 3] << 24);
+
+ return Float.intBitsToFloat(value);
+ }
+
+ public static int getBatteryPerc(double batteryPercentage) {
+ if (batteryPercentage >= 1 && batteryPercentage < 6) {
+ return 0;
+ } else if (batteryPercentage > 5 && batteryPercentage < 11) {
+ return 1;
+ } else if (batteryPercentage > 10 && batteryPercentage < 21) {
+ return 2;
+ } else if (batteryPercentage > 20 && batteryPercentage < 36) {
+ return 3;
+ } else if (batteryPercentage > 35 && batteryPercentage < 71) {
+ return 4;
+ } else if (batteryPercentage > 70 && batteryPercentage < 96) {
+ return 5;
+ } else if (batteryPercentage > 95 && batteryPercentage < 101 || batteryPercentage == 0) {
+ return 6;
+ }
+ return -1;
+ }
+
+ private String getStatusType(String alarmCode) {
+ String alarmCodeString = "";
+ if (alarmCode.equals("02")) {
+ alarmCodeString = "LBA";
+ }else if (alarmCode.equals("03")) {
+ alarmCodeString = "SOS";
+ }else if (alarmCode.equals("08")) {
+ alarmCodeString = "VIBALM";
+ } else if (alarmCode.equals("16")) {
+ alarmCodeString = "PWROFF";
+ } else if (alarmCode.equals("15")) {
+ alarmCodeString = "PWRON";
+ } else {
+ alarmCodeString = "NDFND";
+ }
+ return alarmCodeString;
+ }
+
+}
diff --git a/test/org/traccar/protocol/T800XProtocolDecoderTest.java b/test/org/traccar/protocol/T800XProtocolDecoderTest.java
new file mode 100644
index 000000000..df796013f
--- /dev/null
+++ b/test/org/traccar/protocol/T800XProtocolDecoderTest.java
@@ -0,0 +1,32 @@
+package org.traccar.protocol;
+
+import junit.framework.TestCase;
+import org.jboss.netty.buffer.ChannelBuffers;
+import org.junit.Test;
+import org.traccar.helper.ChannelBufferTools;
+import org.traccar.helper.TestDataManager;
+
+/**
+ * Created by Ankit on 21-10-2015.
+ */
+public class T800XProtocolDecoderTest extends TestCase {
+
+ @Test
+ public void testDecode() throws Exception {
+
+ T800XProtocolDecoder decoder = new T800XProtocolDecoder(new TestDataManager(), null, null);
+
+ assertNull(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(ChannelBufferTools.convertHexString(
+ "232301001500020357367031063979150208625010"))));
+
+ /* assertNull(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(ChannelBufferTools.convertHexString(
+ "6767030004001A0001"))));*/
+
+ /* assertNull(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(ChannelBufferTools.convertHexString(
+ "6767070088001050E2281400FFFFFFFF02334455660333445566043344556605AA00000007334455660A334455660B334455660C4E2000000DAA0000000E334455660F3344556610AAAA000011334455661C334455661F334455662133445566423344556646334455664D334455665C334455665E33445566880000000089000000008A000000008B00000000"))));
+*/
+ /* verify(decoder.decode(null, null, ChannelBuffers.wrappedBuffer(ChannelBufferTools.convertHexString(
+ "676702001b03c5538086df0190c1790b3482df0f0157020800013beb00342401"))));
+*/
+ }
+} \ No newline at end of file