package org.yamcs.tctm; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.zip.GZIPInputStream; import org.yamcs.ConfigurationException; import org.yamcs.YConfiguration; import org.yamcs.archive.PacketWithTime; import org.yamcs.utils.CcsdsPacket; import org.yamcs.utils.StringConverter; import org.yamcs.utils.TimeEncoding; /** * Plays files in pacts format, hrdp format or containing raw ccsds packets. * @author nm * */ public class TmFileReader { protected InputStream inputStream; int fileoffset = 0; int packetcount = 0; /** * Constructs a reader for telemetry files. It reads the first two bytes to see if it's gzip * @param fileName * @throws IOException */ public TmFileReader(String fileName) throws IOException { inputStream = new FileInputStream(fileName); boolean gzip = false; //read the first two bytes to check if it's gzip byte[] b = new byte[2]; int x = inputStream.read(b); if((x==2) && (b[0]==0x1F) && ((b[1]&0xFF)==0x8B)) { gzip = true; } inputStream.close(); if(gzip) { inputStream = new BufferedInputStream(new GZIPInputStream(new FileInputStream(fileName))); } else { inputStream = new BufferedInputStream(new FileInputStream(fileName)); } } public PacketWithTime readPacket(long rectime) throws IOException { int res; byte[] buffer; byte[] fourb=new byte[4]; res = inputStream.read(fourb); if ( res == -1 ) { inputStream.close(); return null; } else if(res!=4){ System.err.println("fourb: "+StringConverter.arrayToHexString(fourb)); inputStream.close(); throw new IOException("Could only read "+res+" out of 4 bytes. Corrupted file?"); } byte[] ccsdshdr=new byte[16]; int ccsdshdroffset=0; boolean isPacts=false; if((fourb[2]==0)&&(fourb[3]==0)) {//hrdp packet: first 4 bytes are the size in little endian byte[] b=new byte[6]; res=inputStream.read(b); if(res!=6) { inputStream.close(); throw new IOException("Could only read "+res+" out of 6 bytes. Corrupted file?"); } else { ByteBuffer bb=ByteBuffer.wrap(b); long unixTimesec=(0xFFFFFFFFL & (long)bb.getInt(1))+315964800L; int unixTimeMicrosec=(bb.get()&0xFF)*(1000000/256); rectime=TimeEncoding.fromUnixTime(unixTimesec,unixTimeMicrosec); } } else if ((fourb[0] & 0xe8) == 0x08) {// CCSDS packet System.arraycopy(fourb, 0, ccsdshdr, 0, 4); ccsdshdroffset=4; } else {//pacts packet isPacts=true; // read ASCII header up to the second blank int i, j; StringBuilder hdr = new StringBuilder(); j = 0; for(i=0;i<4;i++) { hdr.append((char)fourb[i]); if ( fourb[i] == 32 ) { ++j; } } while((j < 2) && (i < 20)) { int c = inputStream.read(); if(c==-1) { inputStream.close(); throw new IOException("short PaCTS ASCII header: '"+ hdr.toString() + "'"); } hdr.append((char)c); if ( c == 32 ) { ++j; } i++; } if ( i == 20 ) { inputStream.close(); throw new IOException("ASCII header too long, probably not a PaCTS archive file: '" + hdr.toString() + "'"); } } res = inputStream.read(ccsdshdr, ccsdshdroffset, 16-ccsdshdroffset); //System.out.println("Read ccsdshdr: "+StringConvertors.arrayToHexString(ccsdshdr)); if (res != 16-ccsdshdroffset) { inputStream.close(); throw new IOException("CCSDS packet header short read " + res + "/16-ccsdshdroffset"); } int len = ((ccsdshdr[4] & 0xff)<<8) + (ccsdshdr[5] & 0xff) + 7; if((len<16)||len>CcsdsPacket.MAX_CCSDS_SIZE) { inputStream.close(); throw new IOException("invalid ccsds packet of length "+len+". Corrupted file?"); } buffer = Arrays.copyOf(ccsdshdr, len); res = inputStream.read(buffer, 16, len - 16); if (res != len - 16) { inputStream.close(); throw new IOException("CCSDS packet body short read " + res + "/" + (len - 16)); } if(isPacts) { if(inputStream.skip(1)!=1) {// terminator newline inputStream.close(); throw new IOException("no new line at the end of the PaCTS packet"); } } return new PacketWithTime(rectime, CcsdsPacket.getInstant(buffer), buffer); } public void close() throws IOException { inputStream.close(); } public static void main(String[] args) throws IOException, ConfigurationException { YConfiguration.setup(); TmFileReader tfr=new TmFileReader(args[0]); PacketWithTime pwrt; while((pwrt=tfr.readPacket(TimeEncoding.getWallclockTime()))!=null) { CcsdsPacket c=new CcsdsPacket(pwrt.getPacket()); System.out.println("rectime: "+TimeEncoding.toString(pwrt.rectime)+" apid:" +c.getAPID()+" seq: "+c.getSequenceCount()+" coarse: "+c.getCoarseTime()+" fine: "+c.getFineTime()+ " time: "+ TimeEncoding.toCombinedFormat(c.getInstant())+" received: "+TimeEncoding.toCombinedFormat(pwrt.rectime)+" delta: "+(pwrt.rectime-c.getInstant())); } } }