package org.yamcs.utils; import java.io.BufferedWriter; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.yamcs.protobuf.Pvalue; import org.yamcs.protobuf.Pvalue.ParameterValue; import org.yamcs.protobuf.Yamcs.NamedObjectId; import org.yamcs.protobuf.Yamcs.Value; import com.csvreader.CsvWriter; /** * Formats in tab separated format parameters. The list of the possible parameters has to be known in advance. * @author nm * */ public class ParameterFormatter { protected BufferedWriter writer; protected boolean printTime=true; protected boolean printRaw=false; protected boolean printMonitoring=false; protected boolean printUnique=false; protected boolean keepValues=false; //if set to true print the latest known value of a parameter even for parameters not retrieved in a packet protected boolean writeHeader=true; protected boolean allParametersPresent = false; // true = print only those lines that contain all parameters' values protected int timewindow = -1; // [ms], -1 = no window at all String previousLine; long lastLineInstant; protected int unsavedLineCount; Map<NamedObjectId, ParameterValue> subscribedParameters=new LinkedHashMap<NamedObjectId, ParameterValue>(); protected int linesSaved, linesReceived; protected boolean first=true; static char DEFAULT_COLUMN_SEPARATOR = '\t'; CsvWriter csvWriter; char columnSeparator = DEFAULT_COLUMN_SEPARATOR; public ParameterFormatter(BufferedWriter writer, Collection<NamedObjectId> paramList) { this(writer, paramList, DEFAULT_COLUMN_SEPARATOR); } public ParameterFormatter(BufferedWriter writer, Collection<NamedObjectId> paramList, char columnSeparator) { this.writer=writer; for(NamedObjectId id:paramList){ subscribedParameters.put(id,null); } this.columnSeparator = columnSeparator; if(writer != null) csvWriter = new CsvWriter(writer, this.columnSeparator); } public void updateWriter(OutputStream outputStream, Charset charset) { if(csvWriter != null) { csvWriter.close(); } csvWriter = new CsvWriter(outputStream, columnSeparator, charset); } public void setPrintRaw(boolean printRaw) { this.printRaw = printRaw; } public void setPrintMonitoring(boolean printMonitoring) { this.printMonitoring = printMonitoring; } public void setPrintTime(boolean printTime) { this.printTime = printTime; } public void setPrintUnique(boolean printUnique) { this.printUnique = printUnique; } public void setWriteHeader(boolean writeHeader) { this.writeHeader = writeHeader; } public void setAllParametersPresent(boolean allParametersPresent) { this.allParametersPresent = allParametersPresent; } public void setKeepValues(boolean keepValues) { this.keepValues = keepValues; } public void setTimeWindow(int timewindow) { this.timewindow = timewindow; } public void resetTimeWindow() { this.timewindow = -1; } private void writeHeader() throws IOException { // print header line with ops names List<String> h = new ArrayList<String>(); if (printTime) { h.add("Time"); } for(NamedObjectId noid:subscribedParameters.keySet()) { h.add(noid.getName()); if(printRaw) h.add(noid.getName() + "_RAW"); if(printMonitoring) h.add(noid.getName() + "_MONITORING"); } csvWriter.writeRecord(h.toArray(new String[0])); } /** * adds new parameters - if they are written to the output buffer or not depends on the settings * @param parameterList * @throws IOException */ public void writeParameters(List<ParameterValue> parameterList) throws IOException { long t=parameterList.get(0).getGenerationTime(); if((timewindow==-1) || (t - lastLineInstant > timewindow)) { writeParameters(); lastLineInstant = t; if(!keepValues) { for(Entry<NamedObjectId, ParameterValue>entry :subscribedParameters.entrySet()) { entry.setValue(null); } } } for(int i=0;i<parameterList.size();i++) { ParameterValue pv=parameterList.get(i); subscribedParameters.put(pv.getId(), pv); } linesReceived++; ++unsavedLineCount; } protected void writeParameters() throws IOException { if(first) { if(writeHeader) { writeHeader(); } first=false; } if (unsavedLineCount == 0) { return; } List<String> l = new ArrayList<String>(); StringBuilder sb=new StringBuilder(); boolean skip = false; for(Entry<NamedObjectId, ParameterValue>entry :subscribedParameters.entrySet()) { ParameterValue pv=entry.getValue(); if(pv!=null) { Value ev=pv.getEngValue(); if(ev!=null) { sb.append(StringConverter.toString(ev, false)); l.add(StringConverter.toString(ev, false)); } else { System.err.println("got parameter without an engineering value for "+entry.getKey()); //skip=true; } if(printRaw) { Value rv=pv.getRawValue(); if(rv!=null) { sb.append(StringConverter.toString(rv, false)); l.add(StringConverter.toString(rv, false)); } else { l.add(""); } } if(printMonitoring) { Pvalue.MonitoringResult mr=pv.getMonitoringResult(); if(mr!=null) { sb.append(mr.name()); l.add(mr.name()); } else { l.add(""); } } } else { if (allParametersPresent) { skip = true; break; } else { l.add(""); if(printRaw) { l.add(""); } } } } if (!skip) { final String line=sb.toString(); if(!printUnique || !line.equals(previousLine)) { if(printTime) { l.add(0, TimeEncoding.toString(lastLineInstant)); } csvWriter.writeRecord(l.toArray(new String[0])); previousLine=line; linesSaved++; } else { skip=true; } } unsavedLineCount = 0; } public void flush() { csvWriter.flush(); } public void close() throws IOException { writeParameters();//write the remaining parameters csvWriter.close(); } public int getLinesSaved() { return linesSaved; } public int getLinesReceived() { return linesReceived; } }