All Downloads are FREE. Search and download functionalities are using the official Maven repository.

lrgs.noaaportrecv.PdiNoaaportProtocol Maven / Gradle / Ivy

Go to download

A collection of software for aggregatting and processing environmental data such as from NOAA GOES satellites.

The newest version!
/**
 * $Id$
 *
 * Author: Mike Maloney, Cove Software LLC.
 *  
 * This is open-source software. You are free to copy and use this
 * source code for your own purposes, except that no part of the information
 * contained in this file may be claimed to be proprietary.
 *
 * Except for specific contractual terms to the federal 
 * government, this source code is provided completely without warranty.
 * 
 *  $Log$
 *  Revision 1.4  2013/02/28 16:50:32  mmaloney
 *  Updates for PDI.
 *
 *  Revision 1.3  2013/02/04 19:07:48  mmaloney
 *  Testing for PDI interface
 *
 *  Revision 1.2  2013/01/30 21:28:54  mmaloney
 *  PDI Initialization
 *
 *  Revision 1.1  2013/01/30 20:39:51  mmaloney
 *  Added new PDI Noaaport Stuff.
 *
 */
package lrgs.noaaportrecv;

import ilex.util.ArrayUtil;
import ilex.util.Logger;

import java.io.IOException;
import java.io.InputStream;

import lrgs.noaaportrecv.NoaaportProtocol.States;

/**
 * This class extends the normal NoaaportProtocol for the PDI
 * (Planetary Data Inc) NOAAPORT socket protocol.
 * The protocol divides the interaction into packets. Packets
 * must be received and the entire message reconstructed.
 */
public class PdiNoaaportProtocol extends NoaaportProtocol
{
	private enum ByteState { StartFlag, FrameSize, DataFrame, MethodFlag, HeaderString };
	private ByteState byteState = ByteState.StartFlag;
	private int frameSizeByte = 0, dataFrameByte = 0, headerStringByte = 0;
	private int dataFrameLength = 0;
	private byte dataFrame[] = null;
	private int numMessagesReceived = 0;

	PdiNoaaportProtocol(InputStream input, NoaaportRecv noaaportRecv,
		NoaaportConnection parent, String clientName)
		throws IOException
	{
		super(input, noaaportRecv, parent, clientName);
		mb_len = 0;
	}

	/**
	 * This method is called repeatedly by the thread servicing this client.
	 */
	protected void read()
	{
		noaaportRecv.setStatus("Receiving");
		
		try { while(byteProtocol() != -1); }
		catch(IOException ex)
		{
			warning("" + NoaaportRecv.EVT_RECV_FAILED
				+ " Error on connection to " + clientName + ": " + ex
				+ ", numMessagesReceived=" + numMessagesReceived);
			disconnect();
		}
	}
	
	/**
	 * ByteState steps through packet bytes to construct packets.
	 * It buffers packet data and calls packetProtocol when it has a complete one.
	 */
	private int byteProtocol()
		throws IOException
	{
		int c = readByte();
		if (c != -1)
			switch(byteState)
			{
			case StartFlag:
				startFlag(c);
				break;
			case FrameSize:
				frameSize(c);
				break;
			case DataFrame:
				dataFrame(c);
				break;
			case MethodFlag:
				methodFlag(c);
				break;
			case HeaderString:
				headerString(c);
				break;
			}
		return c;
	}

	private void startFlag(int c)
		throws IOException
	{
		Logger.instance().debug1(NoaaportRecv.module + " startFlag=" + c);
		switch(c)
		{
		case 0: // data frame
			frameSizeByte = 0;
			dataFrameLength = 0;
			byteState = ByteState.FrameSize;
			break;
		case 1: // header frame
			headerStringByte = 0;
			byteState = ByteState.MethodFlag;
			break;
		case 2: // tail frame
			processMessage(); // in parent NoaaportProtocol class.
			byteState = ByteState.StartFlag;
			break;
		case 3: // uncompressed data frame
			throw new IOException("Uncompressed Data Frame Error received.");
		case 4: // abort message
			warning("Abort Frame Received");
			frameSizeByte = dataFrameLength = 0;
			dataFrame = null;
			byteState = ByteState.StartFlag;
			break;
		default:
			throw new IOException("Invalid PDI packet start flag " + c);
		}
	}

	private void frameSize(int c)
		throws IOException
	{
		// Sometimes frames are 0 filled, sometimes, space filled. Allow either.
		if (c == (int)' ' && dataFrameLength == 0)
			c = (int)'0';
		
		if (!Character.isDigit(c))
			throw new IOException(
				"Non-digit in PDI frame size field '" + c 
				+ "' (" + c + "): Frame aborted.");
		dataFrameLength = dataFrameLength * 10 + (c - (int)'0');
		if (++frameSizeByte >= 4)
		{
			byteState = ByteState.DataFrame;
			dataFrameByte = 0;
			dataFrame = new byte[dataFrameLength];
			debug(" frameLength=" + dataFrameLength);
//			inProductHeader = true;
		}
	}

	private void dataFrame(int c)
		throws IOException
	{
		dataFrame[dataFrameByte++] = (byte)c;
		if (dataFrameByte == dataFrameLength)
		{
			processDataFrame();
			byteState = ByteState.StartFlag;
			dataFrameLength = 0;
			dataFrame = null;
		}
	}
	
	/** First byte after a startFlag = Header */
	private void methodFlag(int c)
	{
		Logger.instance().debug1("PdiNoaaportProtocol: Header method=" + c);
		headerStringByte = 0;
		byteState = ByteState.HeaderString;
	}

	/** 256 bytes of 'header' that we ignore. */
	private void headerString(int c)
	{
		// Ignore header strings.
		if (++headerStringByte >= 256)
			byteState = ByteState.StartFlag;
	}
	
	private void processDataFrame()
		throws IOException
	{
		if (dataFrameLength + mb_len > MESSAGE_MAX)
			throw new IOException("Message too long. Max is " + MESSAGE_MAX);
		for(int i=0; i




© 2015 - 2024 Weber Informatics LLC | Privacy Policy