HuskyPacketReader.java
Go to the documentation of this file.
00001 package com.github.c77.base_driver.husky;
00002 
00003 import org.apache.commons.codec.binary.Hex;
00004 import org.apache.commons.logging.Log;
00005 import org.apache.commons.logging.LogFactory;
00006 
00007 import java.nio.ByteBuffer;
00008 import java.nio.ByteOrder;
00009 
00013 public class HuskyPacketReader {
00014     public enum parserState {
00015         READY, PARTIAL
00016     };
00017     private parserState curState;
00018     private volatile byte[] stored;
00019     private int storedSize;
00020 
00021     private int storedIndex;
00022     private HuskyPacket parsedPacket;
00023 
00024     private static final Log log = LogFactory.getLog(HuskyPacketReader.class);
00025 
00026     public HuskyPacketReader() {
00027         curState = parserState.READY;
00028 
00029         stored = new byte[500]; // Should be big enough for the biggest packets
00030         storedSize = 0;
00031         storedIndex = 0;
00032     }
00033 
00038     public HuskyPacket parse(ByteBuffer buffer) throws HuskyParserException {
00039         // Samples:
00040         //  aa0df2000c030000000402550800de8f  (echo:out of range)
00041         //  aa0df20008040000000402550100d829
00042         //  aa0df200f7 | 030000000402550800ef4f (split message)
00043         //  aa0d | f200 d310 0000 0004 0255 0000 c42c
00044 
00045         int bufferSize = buffer.array().length;
00046         if(curState == parserState.READY) {
00047             // Initialize a new buffer copy
00048             buffer.get(stored, 0, bufferSize);
00049             storedSize = bufferSize;
00050             parsedPacket = new HuskyPacket();
00051         } else {
00052             // Add to the previous buffer and keep parsing
00053             buffer.get(stored, storedSize, bufferSize);
00054             storedSize += bufferSize;
00055         }
00056 
00057         ByteBuffer bufferParse = ByteBuffer.wrap(stored);
00058         bufferParse.order(ByteOrder.LITTLE_ENDIAN);
00059         curState = parserState.PARTIAL;
00060 main:   while(storedIndex < storedSize) {
00061             switch(storedIndex) {
00062                 case 0:     // SOH
00063                     log.debug("Parsing SOH");
00064                     parsedPacket.soh = bufferParse.get(storedIndex);
00065                     if(parsedPacket.soh != (byte)0xAA) {
00066                         // Reset state so that we can wait until the correct packet start.
00067                         storedSize = 0;
00068                         storedIndex = 0;
00069                         curState = parserState.READY;
00070                         throw new HuskyParserException("SOH byte doesn't match: " + parsedPacket.soh);
00071                     }
00072                     storedIndex += 1;
00073                     break;
00074                 case 1:     // length
00075                     log.debug("Parsing length");
00076                     parsedPacket.length = bufferParse.get(storedIndex);
00077                     storedIndex += 1;
00078                     break;
00079                 case 2:     // length complement
00080                     log.debug("Parsing length complement");
00081                     parsedPacket.lengthComplement = bufferParse.get(storedIndex);
00082                     // TODO: Verify complement against length
00083                     storedIndex += 1;
00084                     break;
00085                 case 3:     // version
00086                     log.debug("Parsing version");
00087                     parsedPacket.version = bufferParse.get(storedIndex);
00088                     // TODO: Verify version
00089                     storedIndex += 1;
00090                     break;
00091                 case 4:     // timestamp
00092                     log.debug("Parsing timestamp");
00093                     // Make sure we have enough data to parse this otherwise skip
00094                     if(storedSize - storedIndex < 4) {
00095                         break main;
00096                     }
00097                     parsedPacket.timestamp = bufferParse.getInt(storedIndex);
00098                     storedIndex += 4;
00099                     break;
00100                 case 8:     // flags
00101                     log.debug("Parsing flags");
00102                     parsedPacket.flags = bufferParse.get(storedIndex);
00103                     storedIndex += 1;
00104                     break;
00105                 case 9:     // message type
00106                     log.debug("Parsing message type");
00107                     parsedPacket.messageType = bufferParse.getChar(storedIndex);
00108                     if(storedSize - storedIndex < 2) {
00109                         break main;
00110                     }
00111                     storedIndex += 2;
00112                     break;
00113                 case 11:     // stx
00114                     log.debug("Parsing STX");
00115                     parsedPacket.stx = bufferParse.get(storedIndex);
00116                     if(parsedPacket.stx != (byte)0x55) {
00117                         throw new HuskyParserException("STX byte doesn't match: " + parsedPacket.stx);
00118                     }
00119                     storedIndex += 1;
00120                     break;
00121                 case 12:     // payload and CRC
00122                     log.debug("Parsing payload and CRC");
00123                     int payloadAndCrcLength = parsedPacket.length - 9;
00124                     if(storedSize - storedIndex < payloadAndCrcLength) {
00125                         break main;
00126                     }
00127                     parsedPacket.payload = new byte[payloadAndCrcLength - 2];
00128                     System.arraycopy(stored, 12, parsedPacket.payload, 0, parsedPacket.payload.length);
00129                     bufferParse.getChar(storedIndex + parsedPacket.payload.length);
00130                     // TODO: Verify checksum
00131                     storedIndex = 0;
00132                     curState = parserState.READY;
00133                     break main;
00134             }
00135         }
00136 
00137         if(curState == parserState.READY) {
00138             return parsedPacket;
00139         } else {
00140             return null;
00141         }
00142     }
00143 
00147     public static void main(String args[]) throws java.lang.Exception {
00148         HuskyPacketReader reader = new HuskyPacketReader();
00149 
00150         // Try parsing entire packet in one shot (most common method)
00151         HuskyPacket packet = tryParse(reader, "aa0df2000c030000000402550800de8f");
00152         System.out.println("Packet = " + packet);
00153 
00154         // Try parsing packet in two passes
00155         System.out.println("Packet 1/2 = " + tryParse(reader, "aa0df200f7"));
00156         System.out.println("Packet 1/2 = " + tryParse(reader, "030000000402550800ef4f"));
00157     }
00158     private static HuskyPacket tryParse(HuskyPacketReader reader, String hexArrayString) throws java.lang.Exception {
00159         return reader.parse(ByteBuffer.wrap(Hex.decodeHex(hexArrayString.toCharArray())));
00160     }
00161 }


android_base_controller
Author(s):
autogenerated on Fri Aug 28 2015 10:04:47