dti.tdl.messaging.TDLMessageHandler.java Source code

Java tutorial

Introduction

Here is the source code for dti.tdl.messaging.TDLMessageHandler.java

Source

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package dti.tdl.messaging;

import com.google.common.primitives.Longs;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.LinkedList;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.CRC32;
import java.util.zip.Checksum;

/**
 *
 * @author wichai.p
 */
public class TDLMessageHandler {

    public static boolean hasUnfinishedMsg = false;
    public final static LinkedList<String> txStack = new LinkedList<String>();
    public final static ConcurrentLinkedQueue<TDLMessage> rxStack = new ConcurrentLinkedQueue<TDLMessage>();
    public final static LinkedList<String> cmdReqStack = new LinkedList<String>();
    public final static LinkedList<String> cmdResStack = new LinkedList<String>();
    public static boolean isCmdMode = false;
    public static double messageMaxBytes = 100;
    public static double messageOverheadBytes = 21;

    public static void deFraming(byte[] bytes) {
        int size = bytes.length;
        int startIdx = -1;
        int endIdx = -1;
        int startMsgIdx = -1;
        int endMsgIdx = -1;
        //        try {
        String rxMsgT = new String(bytes);

        String rcvStr = "Rx Frame: ";
        for (int j = 0; j < bytes.length; j++) {
            rcvStr = rcvStr + " " + (int) bytes[j];

        }
        System.out.println(rcvStr);
        //            System.out.println(rxMsgT);
        //            System.out.println(size);
        //        } catch (UnsupportedEncodingException ex) {
        //            Logger.getLogger(TDLMessageHandler.class.getName()).log(Level.SEVERE, null, ex);
        //        }
        //        for (int k = 0; k < bytes.length; k++) {
        //            System.out.println("Rx frame Byte " + k + ": " + (int) bytes[k]);
        //        }
        for (int i = 0; i < size; i++) {
            if (bytes[i] == (byte) 1) {
                if (startIdx == -1)
                    startIdx = i;

            }

            if (bytes[i] == (byte) 2) {
                if (startMsgIdx == -1)
                    startMsgIdx = i;

            }
            if (bytes[i] == (byte) 3) {
                if (endMsgIdx == -1 && i > startIdx && i > startMsgIdx)
                    endMsgIdx = i;

            }
            if (bytes[i] == (byte) 4) {
                if (endIdx == -1 && i > startIdx && i > startMsgIdx && i > endMsgIdx && bytes[i - 1] == (byte) 3)
                    endIdx = i;

            }
        }

        if (startIdx == -1 || endIdx == -1 || endMsgIdx < startMsgIdx || endIdx < startMsgIdx || endIdx < endMsgIdx
                || startMsgIdx < startIdx) {
            String err = "Corrupted Message: invalid frame";
            TDLMessage rxMsg = new TDLMessage(null, null, null, null, (byte) 48, err.getBytes());
            //            rxStack.add(rxMsg);
            rxStack.offer(rxMsg);
            return;
        }
        byte[] msgType = { bytes[startIdx + 1] };
        byte[] fromId = { bytes[startIdx + 2], bytes[startIdx + 3] };
        byte[] toId = { bytes[startIdx + 4], bytes[startIdx + 5] };
        byte[] profileId = { bytes[startIdx + 6], bytes[startIdx + 7], bytes[startIdx + 8], bytes[startIdx + 9] };
        //int checksumSize = startMsgIdx - startIdx+9;
        byte[] checksum = Arrays.copyOfRange(bytes, startIdx + 10, startIdx + 18);
        byte[] msg = Arrays.copyOfRange(bytes, startMsgIdx + 1, endMsgIdx);
        //try {
        //      String rxMsg = new String(msg);
        //      System.out.println(rxMsg);

        long newChecksum = CRC32Checksum(msg);
        //        System.out.println(startIdx);
        //        System.out.println(startMsgIdx);
        //        System.out.println(endIdx);
        //        System.out.println(checksum.length);
        //long receiveChecksum = ByteUtil.bytesToLong(checksum);
        long receiveChecksum = Longs.fromByteArray(checksum);
        //System.out.println(checksum.toString());
        //System.out.println(newChecksum);
        //System.out.println(receiveChecksum);
        String profileStr = new String(profileId);
        String fromStr = "";
        for (int i = 0; i < fromId.length; i++) {
            int fromBI = (int) fromId[i];
            fromStr = fromStr + String.format("%02x", Byte.parseByte(Integer.toString(fromBI)));
        }
        if (newChecksum != receiveChecksum) {
            String err = "Corrupted Message: checksum not matched";
            TDLMessage rxMsgObj = new TDLMessage(profileStr, fromStr, toId.toString(), null, (byte) 48,
                    err.getBytes());
            //            rxStack.add(rxMsg);
            rxStack.offer(rxMsgObj);
            return;
        }

        TDLMessage rxMsgObj = new TDLMessage(profileStr, fromStr, toId.toString(), null, msgType[0], msg);
        //            rxStack.add(rxMsg);
        rxStack.offer(rxMsgObj);
        //        } catch (UnsupportedEncodingException ex) {
        //        }

    }

    public static byte[] pplitobytes(PPLI position) {
        double[] ppliDouble = new double[5];
        double lat = position.getPosLat();
        double lon = position.getPosLon();
        double speed = position.getSpeed();
        double tc = position.getTrueCourse();
        double mv = position.getMagVariation();
        ppliDouble[0] = lat;
        ppliDouble[1] = lon;
        ppliDouble[2] = speed;
        ppliDouble[3] = tc;
        ppliDouble[4] = mv;

        byte[] ppliDblBytes = TDLMessageHandler.double2Byte(ppliDouble);

        byte[] ppliBytes = new byte[ppliDblBytes.length + 12];

        System.arraycopy(ppliDblBytes, 0, ppliBytes, 0, ppliDblBytes.length);

        System.arraycopy(position.getPosDate().getBytes(), 0, ppliBytes, ppliDblBytes.length,
                position.getPosDate().getBytes().length);

        System.arraycopy(position.getPosTime().getBytes(), 0, ppliBytes,
                ppliDblBytes.length + position.getPosDate().getBytes().length,
                position.getPosTime().getBytes().length);

        return ppliBytes;
    }

    public static PPLI bytestoPPLI(byte[] data) {
        PPLI decodedPPLI = new PPLI();
        byte[] ppliDblBytes = Arrays.copyOfRange(data, 0, 40);
        double[] ppliDouble = TDLMessageHandler.byte2Double(data, false);
        decodedPPLI.setPosLat(ppliDouble[0]);
        decodedPPLI.setPosLon(ppliDouble[1]);
        decodedPPLI.setSpeed(ppliDouble[2]);
        decodedPPLI.setTrueCourse(ppliDouble[3]);
        decodedPPLI.setMagVariation(ppliDouble[4]);
        decodedPPLI.setPosDate(new String(Arrays.copyOfRange(data, 40, 46)));
        decodedPPLI.setPosTime(new String(Arrays.copyOfRange(data, 46, 52)));

        return decodedPPLI;
    }

    public static void constructFrame(TDLMessage message) {
        byte[] start = { (byte) 1 };
        byte[] startMsg = { (byte) 2 };
        byte[] endMsg = { (byte) 3 };
        byte[] end = { (byte) 4 };
        byte[] profile = message.getProfileId().substring(0, 4).getBytes(); //4 bytes profile id
        byte[] msgType = { message.getMsgType() }; // 1 byte message type
        byte[] from = hexStringToByteArray(message.getFromId());
        byte[] to = hexStringToByteArray(message.getToId());
        byte[] data = message.getMsg();
        int numBlk = 1;

        if (data.length > TDLMessageHandler.messageMaxBytes) {
            numBlk = (int) (data.length / TDLMessageHandler.messageMaxBytes);
            if (data.length % TDLMessageHandler.messageMaxBytes > 0) {
                numBlk++;
            }

        }
        //String utf8msg = new String()
        long checksum = CRC32Checksum(data);

        byte[] checksumBytes = Longs.toByteArray(checksum);
        System.out.println("checksum len = " + checksumBytes.length);
        String checksumStr = "Checksum: ";
        for (int j = 0; j < checksumBytes.length; j++) {
            checksumStr = checksumStr + " " + (int) checksumBytes[j];

        }
        System.out.println(checksumStr);
        byte[] frame = null;
        int msgLength = data.length;
        int msgIdx = 0;
        for (int i = 0; i < numBlk; i++) {
            if (msgLength > TDLMessageHandler.messageMaxBytes) {
                msgLength = (int) (msgLength - TDLMessageHandler.messageMaxBytes);
            }
            int msgBlkLength = (int) TDLMessageHandler.messageMaxBytes;
            if (i == numBlk - 1) {
                msgBlkLength = msgLength;
            }
            msgIdx = (int) (TDLMessageHandler.messageMaxBytes * i);
            frame = new byte[start.length + 1 + from.length + to.length + profile.length + checksumBytes.length
                    + startMsg.length + msgBlkLength + endMsg.length + end.length];
            System.arraycopy(start, 0, frame, 0, 1);
            System.arraycopy(msgType, 0, frame, 1, 1);
            System.arraycopy(from, 0, frame, 2, from.length);
            System.arraycopy(to, 0, frame, 2 + from.length, to.length);
            System.arraycopy(profile, 0, frame, 2 + from.length + to.length, profile.length);
            System.arraycopy(checksumBytes, 0, frame, 2 + from.length + to.length + profile.length,
                    checksumBytes.length);
            System.arraycopy(startMsg, 0, frame,
                    2 + from.length + to.length + profile.length + checksumBytes.length, startMsg.length);
            System.arraycopy(Arrays.copyOfRange(data, msgIdx, msgIdx + msgBlkLength), 0, frame,
                    2 + from.length + to.length + profile.length + checksumBytes.length + startMsg.length,
                    msgBlkLength);
            System.arraycopy(endMsg, 0, frame, 2 + from.length + to.length + profile.length + checksumBytes.length
                    + startMsg.length + msgBlkLength, endMsg.length);
            System.arraycopy(end, 0, frame, 2 + from.length + to.length + profile.length + checksumBytes.length
                    + startMsg.length + msgBlkLength + endMsg.length, end.length);

            String txMsg = null;
            StringBuilder builder = new StringBuilder();

            for (int j = 0; j < frame.length; j++) {
                if (j < frame.length - 1) {
                    builder.append((int) frame[j] + ",");
                } else {
                    builder.append((int) frame[j]);
                }
            }
            txMsg = builder.toString();

            String[] txBytesStrArray = txMsg.split(",");
            byte[] txBytes = new byte[txBytesStrArray.length];
            //String frameMsg = "Frame content (before): ";
            for (int j = 0; j < txBytesStrArray.length; j++) {
                int byteInt = Integer.parseInt(txBytesStrArray[j]);
                //frameMsg = frameMsg+" "+byteInt;
                txBytes[j] = (byte) byteInt;
            }
            //System.out.println(frameMsg);
            txStack.add(txMsg);
        }
    }

    public static void SimFraming(TDLMessage message) {
        byte[] start = { (byte) 1 };
        byte[] startMsg = { (byte) 2 };
        byte[] endMsg = { (byte) 3 };
        byte[] end = { (byte) 4 };
        byte[] profile = message.getProfileId().substring(0, 4).getBytes(); //4 bytes profile id
        byte[] msgType = { message.getMsgType() }; // 1 byte message type
        byte[] from = hexStringToByteArray(message.getFromId());
        byte[] to = hexStringToByteArray(message.getToId());
        byte[] data = message.getMsg();
        int numBlk = 1;

        if (data.length > TDLMessageHandler.messageMaxBytes) {
            numBlk = (int) (data.length / TDLMessageHandler.messageMaxBytes);
            if (data.length % TDLMessageHandler.messageMaxBytes > 0) {
                numBlk++;
            }

        }
        //String utf8msg = new String()
        long checksum = CRC32Checksum(data);

        byte[] checksumBytes = Longs.toByteArray(checksum);

        byte[] frame = null;
        int msgLength = data.length;
        int msgIdx = 0;
        for (int i = 0; i < numBlk; i++) {
            if (msgLength > TDLMessageHandler.messageMaxBytes) {
                msgLength = (int) (msgLength - TDLMessageHandler.messageMaxBytes);
            }
            int msgBlkLength = (int) TDLMessageHandler.messageMaxBytes;
            if (i == numBlk - 1) {
                msgBlkLength = msgLength;
            }
            msgIdx = (int) (TDLMessageHandler.messageMaxBytes * i);
            frame = new byte[start.length + 1 + from.length + to.length + profile.length + checksumBytes.length
                    + startMsg.length + msgBlkLength + endMsg.length + end.length];
            System.arraycopy(start, 0, frame, 0, 1);
            System.arraycopy(msgType, 0, frame, 1, 1);
            System.arraycopy(from, 0, frame, 2, from.length);
            System.arraycopy(to, 0, frame, 2 + from.length, to.length);
            System.arraycopy(profile, 0, frame, 2 + from.length + to.length, profile.length);
            System.arraycopy(checksumBytes, 0, frame, 2 + from.length + to.length + profile.length,
                    checksumBytes.length);
            System.arraycopy(startMsg, 0, frame,
                    2 + from.length + to.length + profile.length + checksumBytes.length, startMsg.length);
            System.arraycopy(Arrays.copyOfRange(data, msgIdx, msgIdx + msgBlkLength), 0, frame,
                    2 + from.length + to.length + profile.length + checksumBytes.length + startMsg.length,
                    msgBlkLength);
            System.arraycopy(endMsg, 0, frame, 2 + from.length + to.length + profile.length + checksumBytes.length
                    + startMsg.length + msgBlkLength, endMsg.length);
            System.arraycopy(end, 0, frame, 2 + from.length + to.length + profile.length + checksumBytes.length
                    + startMsg.length + msgBlkLength + endMsg.length, end.length);

            String txMsg = null;
            StringBuilder builder = new StringBuilder();

            for (int j = 0; j < frame.length; j++) {
                if (j < frame.length - 1) {
                    builder.append((int) frame[j] + ",");
                } else {
                    builder.append((int) frame[j]);
                }
            }
            txMsg = builder.toString();

            String[] txBytesStrArray = txMsg.split(",");
            byte[] txBytes = new byte[txBytesStrArray.length];
            //String frameMsg = "Sim Frame content (before): ";
            for (int j = 0; j < txBytesStrArray.length; j++) {
                int byteInt = Integer.parseInt(txBytesStrArray[j]);
                //frameMsg = frameMsg+" "+byteInt;
                txBytes[j] = (byte) byteInt;
            }
            //System.out.println(frameMsg);
            TDLMessageHandler.deFraming(txBytes);

        }
    }

    public static byte[] getBytesFromQueue() {
        String txBytesStr = txStack.removeFirst();
        String[] txBytesStrArray = txBytesStr.split(",");
        byte[] txBytes = new byte[txBytesStrArray.length];
        String frameMsg = "Tx Frame content: ";
        for (int j = 0; j < txBytesStrArray.length; j++) {
            int byteInt = Integer.parseInt(txBytesStrArray[j]);
            frameMsg = frameMsg + " " + byteInt;
            txBytes[j] = (byte) byteInt;
        }
        System.out.println(frameMsg);
        return txBytes;
    }

    public static byte[] hexStringToByteArray(String s) {
        if (s == null || s == "") {
            s = "0000";
        }
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    public static long CRC32Checksum(byte[] bytes) {
        long checksum = 0;

        Checksum check = new CRC32();
        // update the current checksum with the specified array of bytes
        check.update(bytes, 0, bytes.length);
        // get the current checksum value
        checksum = check.getValue();
        return checksum;

    }

    public static PPLI decodeOwnPosition(String posStr) {
        PPLI pos = new PPLI();
        //pos.posId = "0000";
        String[] posValues = posStr.split(",");
        String posTime = posValues[1];
        String posDate = posValues[9];

        double posLat = degreeToDecimal(posValues[3]);
        double posLon = degreeToDecimal(posValues[5]);
        //        double posLat = Double.parseDouble(posValues[3]);
        //        double posLon = Double.parseDouble(posValues[5]);
        double posSpeed = 0.0;
        if (!posValues[7].isEmpty()) {
            posSpeed = Double.parseDouble(posValues[7]);
        }
        double posTC = 0.0;
        if (!posValues[8].isEmpty()) {
            posTC = Double.parseDouble(posValues[8]);
        }
        double posMV = 0.0;
        if (!posValues[9].isEmpty()) {
            posMV = Double.parseDouble(posValues[9]);
        }
        DateFormat df = new SimpleDateFormat("MMddyy");
        DateFormat tf = new SimpleDateFormat("HHmmss");

        Date today = Calendar.getInstance().getTime();

        String reportDate = df.format(today);
        String reportTime = tf.format(today);
        pos.setPosDate(reportDate);
        pos.setPosTime(reportTime);
        pos.setPosLat(posLat);
        pos.setPosLon(posLon);
        pos.setTrueCourse(posTC);
        pos.setSpeed(posSpeed);
        pos.setMagVariation(posMV);
        return pos;
    }

    public static double degreeToDecimal(String degreeStr) {
        String posMinStr = degreeStr.substring(degreeStr.length() - 8, degreeStr.length());
        String posDegreeStr = degreeStr.substring(0, degreeStr.length() - 8);
        double posMin = Double.parseDouble(posMinStr);
        double posDegree = Double.parseDouble(posDegreeStr);
        return posDegree + posMin / 60;

    }

    public static final byte[] double2Byte(double[] inData) {
        int j = 0;
        int length = inData.length;
        byte[] outData = new byte[length * 8];
        for (int i = 0; i < length; i++) {
            long data = Double.doubleToLongBits(inData[i]);
            outData[j++] = (byte) (data >>> 56);
            outData[j++] = (byte) (data >>> 48);
            outData[j++] = (byte) (data >>> 40);
            outData[j++] = (byte) (data >>> 32);
            outData[j++] = (byte) (data >>> 24);
            outData[j++] = (byte) (data >>> 16);
            outData[j++] = (byte) (data >>> 8);
            outData[j++] = (byte) (data >>> 0);
        }
        return outData;
    }

    public static final double[] byte2Double(byte[] inData, boolean byteSwap) {
        int j = 0, upper, lower;
        int length = inData.length / 8;
        double[] outData = new double[length];
        if (!byteSwap) {
            for (int i = 0; i < length; i++) {
                j = i * 8;
                upper = (((inData[j] & 0xff) << 24) + ((inData[j + 1] & 0xff) << 16) + ((inData[j + 2] & 0xff) << 8)
                        + ((inData[j + 3] & 0xff) << 0));
                lower = (((inData[j + 4] & 0xff) << 24) + ((inData[j + 5] & 0xff) << 16)
                        + ((inData[j + 6] & 0xff) << 8) + ((inData[j + 7] & 0xff) << 0));
                outData[i] = Double.longBitsToDouble((((long) upper) << 32) + (lower & 0xffffffffl));
            }
        } else {
            for (int i = 0; i < length; i++) {
                j = i * 8;
                upper = (((inData[j + 7] & 0xff) << 24) + ((inData[j + 6] & 0xff) << 16)
                        + ((inData[j + 5] & 0xff) << 8) + ((inData[j + 4] & 0xff) << 0));
                lower = (((inData[j + 3] & 0xff) << 24) + ((inData[j + 2] & 0xff) << 16)
                        + ((inData[j + 1] & 0xff) << 8) + ((inData[j] & 0xff) << 0));
                outData[i] = Double.longBitsToDouble((((long) upper) << 32) + (lower & 0xffffffffl));
            }
        }

        return outData;
    }
}