package org.das2.qds.buffer; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.util.Collections; import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; /** * Utility class for reading CCSDS telemetry streams * * @author jbf */ public class CcsdsReader { /** * extend this class to handle a particular packet type. */ public static interface PacketHandler { /** * process the packet return a 0 if the data was processed correctly. * @param packetId * @param buf * @return */ int packet(int packetId, ByteBuffer buf); } //private Map handlers= new HashMap<>(); PacketHandler[] handlers = new PacketHandler[65535]; int offsetCorrection= 0; /** * set the CCSDS offset correction, in case the file has incorrect offsets between packets which can be corrected with * a simple offset. * @param offs */ public void setOffsetCorrection(int offs) { offsetCorrection= offs; } public void addPacketHandler(int packetId, PacketHandler h) { if (packetId > (65535)) { throw new IllegalArgumentException("packetId must be between 0 and 2^16."); } handlers[packetId] = h; } public void parse(File file) throws FileNotFoundException, IOException { RandomAccessFile f = new RandomAccessFile(file, "r"); //FileChannel channel = f.getChannel(); try ( FileChannel channel= f.getChannel() ) { ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0, channel.size()); parse(buf); } } private SortedSet appIds= new TreeSet<>(); public void parse(ByteBuffer buf) throws IOException { int packetNumber = 0; while (buf.remaining() >= 6) { int offset = buf.position(); int b0 = buf.get(offset) & 255; int b1 = buf.get(offset + 1) & 255; int b2 = buf.get(offset + 2) & 255; int b3 = buf.get(offset + 3) & 255; int b4 = buf.get(offset + 4) & 255; int b5 = buf.get(offset + 5) & 255; int apid = ( (b0 & 0x07 ) << 8) | b1; int sequenceCount = ( (b2 & 0x3f ) << 8) | b3; int dataLength = ( (b4 << 8) | b5) + 1; int packetLength = 6 + dataLength; if (packetLength > buf.remaining()) { throw new IOException(String.format("Incomplete packet at offset %d", offset)); } int oldLimit = buf.limit(); buf.limit(offset + packetLength + offsetCorrection); buf.position(offset); ByteBuffer packet = buf.slice(); buf.limit(oldLimit); buf.position(offset); appIds.add(apid); PacketHandler handler = handlers[apid]; if (handler != null) { handler.packet(apid, packet); } buf.position(offset + packetLength + offsetCorrection); packetNumber = packetNumber + 1; } } /** * get the set of appIds. * @return */ public Set getAppIds() { return Collections.unmodifiableSortedSet(appIds); } }