lritdcs.LritDcsFile Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of opendcs Show documentation
Show all versions of opendcs Show documentation
A collection of software for aggregatting and processing environmental data such as from NOAA GOES satellites.
The newest version!
/*
* $Id$
*
* $Log$
* Revision 1.4 2012/12/12 16:01:31 mmaloney
* Several updates for 5.2
*
* Revision 1.3 2009/10/14 13:09:48 mjmaloney
* LRIT updates
*
* Revision 1.2 2009/10/09 14:52:26 mjmaloney
* Added flag bytes and carrier times to LRIT File.
*
* Revision 1.1 2008/04/04 18:21:16 cvs
* Added legacy code to repository
*
* Revision 1.9 2005/12/30 19:40:59 mmaloney
* dev
*
* Revision 1.8 2004/05/18 18:02:09 mjmaloney
* dev
*
* Revision 1.7 2004/04/29 16:11:07 mjmaloney
* Implemented new header fields.
*
* Revision 1.6 2003/08/18 14:47:59 mjmaloney
* bug fixes.
*
* Revision 1.5 2003/08/15 20:13:07 mjmaloney
* dev
*
* Revision 1.4 2003/08/10 02:22:47 mjmaloney
* dev.
*
* Revision 1.3 2003/08/06 23:29:24 mjmaloney
* dev
*
* Revision 1.2 2003/07/28 19:18:24 mjmaloney
* dev
*
* Revision 1.1 2003/07/28 18:16:36 mjmaloney
* Initial version.
*
* Revision 1.1.1.1 2003/07/28 18:13:20 mjmaloney
* LRIT-DCS Project Files
*
*/
package lritdcs;
import java.io.*;
import java.util.Date;
import java.util.TimeZone;
import java.text.SimpleDateFormat;
import java.util.zip.CRC32;
import lrgs.common.DcpMsg;
import lrgs.common.DcpMsgFlag;
import ilex.util.ByteUtil;
import ilex.util.Logger;
public class LritDcsFile
{
/** Priority is 'H'=High, 'M'=Medium, or 'L'=Low
Should use one of the priority values defined in Constants.java.
*/
private char priority;
/// 'e' or 'w', use the values defined in Constants.java
private char spacecraft;
/// The directory in which files are to be created.
private File parentDir;
/// The current file-image we are building.
private byte fileImage[];
/// System time when first message was added to this image.
private long fileStartTime;
/// Number of messages currently in the image.
private int numMessages;
/// Current byte-length of file-image.
private int imageSize;
/// fileImage length is incremented by this amount when necessary.
private static final int ImageIncrement = 20000;
/// Delimiter at start of each DCP message in file: 2 ASCII STX chars.
public static final byte[] MsgDelim = new byte[]{ (byte)2, (byte)2 };
/// Formatter to use for date/time stamp in file names:
private SimpleDateFormat domsatDateFmt = new SimpleDateFormat("yyDDDHHmmss");
private Date lastSave;
private char seqLetter;
/// Used to compute file CRCs.
private CRC32 myCRC;
private byte crcImage[];
private SimpleDateFormat ctimeFmt = new SimpleDateFormat("yyDDDHHmmssSSS");
public LritDcsFile(char priority, File parentDir, char spacecraft)
throws InitFailedException
{
this.priority = priority;
this.parentDir = parentDir;
this.spacecraft = spacecraft;
fileImage = new byte[ImageIncrement];
lastSave = null;
myCRC = new CRC32();
crcImage = new byte[4];
clear();
if (!parentDir.isDirectory())
{
Logger.instance().log(Logger.E_INFORMATION,
"Creating output directory '" + parentDir.getPath() + "'");
boolean success = false;
Exception ex = null;
try { success = parentDir.mkdirs(); }
catch(Exception e) { success = false; ex = e; }
if (!success)
{
String msg =
ex != null ? ex.toString() :
("Cannot create directory '"+parentDir.getPath()+"'");
Logger.instance().fatal("LRIT:" + Constants.EVT_INIT_FAILED
+ "- " + msg);
throw new InitFailedException(msg);
}
}
domsatDateFmt.setTimeZone(TimeZone.getTimeZone("UTC"));
ctimeFmt.setTimeZone(TimeZone.getTimeZone("UTC"));
}
/**
Returns the system-time when the first message was added to this file-
image.
*/
public long getFileStartTime()
{
return fileStartTime;
}
/// Returns the number of messages currently in this file image.
public int getNumMessages()
{
return numMessages;
}
/// Returns the current file-image size.
public int getImageSize()
{
return imageSize;
}
/**
Adds a DCP message to the end of this file's image.
The 'buffer' passed here contains the 37-byte DOMSAT header followed
by the variable length message data. This method parses the
final 5-bytes of the header to determine the message length,
which may be different than the byte-length of the passed buffer.
@throws BadMessageException if passed buffer is invalid or inconsistent.
*/
public synchronized void addMessage(DcpMsg dcpMsg)
throws BadMessageException
{
byte buffer[] = dcpMsg.getData();
// Make sure buffer is at least 37 bytes.
if (buffer.length < 37)
throw new BadMessageException("Message header too short: "
+ buffer.length + " bytes.");
// Parse message length from header
String lenfield = new String(buffer, 32, 5);
int msglen = 0;
for(int i=0; i<5; i++)
{
msglen = msglen * 10;
char c = lenfield.charAt(i);
if (Character.isDigit(c))
msglen = msglen + (int)((byte)c - (byte)'0');
else if (!Character.isWhitespace(c))
throw new BadMessageException("Non-digit in length field '"
+ c + "'");
}
// Make sure buffer length is big enough to accommodate the message.
if (buffer.length < msglen + 37)
throw new BadMessageException(
"Message data is " + buffer.length
+ " but length field says is should be " + msglen);
// Add delimiter to my internal file image.
addBytes(MsgDelim, MsgDelim.length);
// Add the 16-bit flag word.
Date cstart = dcpMsg.getCarrierStart();
Date cstop = dcpMsg.getCarrierStop();
if ((dcpMsg.flagbits & DcpMsgFlag.HAS_CARRIER_TIMES) != 0
&& (cstart == null || cstop == null))
dcpMsg.flagbits &= (~DcpMsgFlag.HAS_CARRIER_TIMES);
byte flagbytes[] = new byte[2];
flagbytes[0] = (byte)((dcpMsg.flagbits>>8) & 0xff);
flagbytes[1] = (byte)(dcpMsg.flagbits & 0xff);
addBytes(flagbytes, 2);
// Copy message header & data into internal file image.
addBytes(buffer, 37 + msglen);
// If this msg had carrier times, add them after the msg data
if ((dcpMsg.flagbits & DcpMsgFlag.HAS_CARRIER_TIMES) != 0)
{
String ctimes = ctimeFmt.format(cstart)
+ ' ' + ctimeFmt.format(cstop);
addBytes(ctimes.getBytes(), ctimes.length());
}
Logger.instance().log(Logger.E_DEBUG3,
"Added priority " + priority + " message[" + numMessages
+ "] from platform "
+ (new String(buffer, 0, 8)) + ", channel "
+ (new String(buffer, 26, 3)) + ", data length=" + msglen);
numMessages++;
}
/// Adds bytes to the end of the image, increasing image size if necessary.
private void addBytes(byte b[], int len)
{
if (imageSize + len >= fileImage.length)
{
int newlen = fileImage.length + ImageIncrement;
while (newlen < imageSize + len)
newlen += ImageIncrement;
Logger.instance().log(Logger.E_DEBUG1,
"Increasing image size from " + fileImage.length + " to "
+ newlen);
byte newImage[] = new byte[newlen];
for(int i=0; i
[N] is the priority, one of 'H', 'M', or 'L'.
[YYDDDHHMMSS] is the current system time when this method is
called. It is the file-creation-time.
[Q] is an ASCII letter from A...Z representing a sequence
number.
[SC] is the GOES spacecraft, 'e' for East, 'w' for West, or
nothing for both.
Returns the File object to which data was saved.
*/
public File saveFile()
throws LritDcsFileException
{
// If this file within same second as last one, increment seq letter.
Date d = new Date();
if (lastSave != null &&
(d.getTime()/1000) == (lastSave.getTime()/1000))
seqLetter = (char)((int)seqLetter + 1);
else
seqLetter = 'A';
lastSave = d;
// Construct file name.
String filename = "p" + priority + "-"
+ domsatDateFmt.format(d) + "-" + seqLetter + ".dcs";
if (spacecraft != Constants.SC_Both)
filename = filename + spacecraft;
// Place the file name in the header & fill remainder with spaces.
for(int i=0; i