package org.yamcs.web.rest.archive; import java.util.ArrayList; import java.util.List; import org.yamcs.protobuf.Alarms.AcknowledgeInfo; import org.yamcs.protobuf.Alarms.AlarmData; import org.yamcs.protobuf.Archive.ColumnData; import org.yamcs.protobuf.Archive.ColumnInfo; import org.yamcs.protobuf.Archive.StreamData; import org.yamcs.protobuf.Archive.StreamInfo; import org.yamcs.protobuf.Archive.TableInfo; import org.yamcs.protobuf.Pvalue.ParameterValue; import org.yamcs.protobuf.Pvalue.TimeSeries; import org.yamcs.protobuf.Yamcs.EndAction; import org.yamcs.protobuf.Yamcs.Event; import org.yamcs.protobuf.Yamcs.NamedObjectId; import org.yamcs.protobuf.Yamcs.ParameterReplayRequest; import org.yamcs.protobuf.Yamcs.ReplayRequest; import org.yamcs.protobuf.Yamcs.ReplaySpeed; import org.yamcs.protobuf.Yamcs.ReplaySpeed.ReplaySpeedType; import org.yamcs.protobuf.Yamcs.Value; import org.yamcs.protobuf.Yamcs.Value.Type; import org.yamcs.utils.TimeEncoding; import org.yamcs.utils.ValueUtility; import org.yamcs.web.HttpException; import org.yamcs.web.rest.RestRequest; import org.yamcs.web.rest.RestRequest.IntervalResult; import org.yamcs.web.rest.archive.RestDownsampler.Sample; import org.yamcs.xtce.Parameter; import org.yamcs.yarch.ColumnDefinition; import org.yamcs.yarch.DataType; import org.yamcs.yarch.Stream; import org.yamcs.yarch.TableDefinition; import org.yamcs.yarch.Tuple; import org.yamcs.yarch.TupleDefinition; import com.google.protobuf.ByteString; import com.google.protobuf.MessageLite; /** * Collects all archive-related conversions performed in the web api (x towards * archive.proto) */ public final class ArchiveHelper { final static TableInfo toTableInfo(TableDefinition def) { TableInfo.Builder infob = TableInfo.newBuilder(); infob.setName(def.getName()); for (ColumnDefinition cdef : def.getKeyDefinition().getColumnDefinitions()) { infob.addKeyColumn(toColumnInfo(cdef)); } for (ColumnDefinition cdef : def.getValueDefinition().getColumnDefinitions()) { infob.addValueColumn(toColumnInfo(cdef)); } return infob.build(); } final static StreamInfo toStreamInfo(Stream stream) { StreamInfo.Builder infob = StreamInfo.newBuilder(); infob.setName(stream.getName()); for (ColumnDefinition cdef : stream.getDefinition().getColumnDefinitions()) { infob.addColumn(toColumnInfo(cdef)); } return infob.build(); } private static ColumnInfo toColumnInfo(ColumnDefinition cdef) { ColumnInfo.Builder infob = ColumnInfo.newBuilder(); infob.setName(cdef.getName()); infob.setType(cdef.getType().toString()); return infob.build(); } public static StreamData toStreamData(Stream stream, Tuple tuple) { StreamData.Builder builder = StreamData.newBuilder(); builder.setStream(stream.getName()); builder.addAllColumn(toColumnDataList(tuple)); return builder.build(); } final static List<ColumnData> toColumnDataList(Tuple tuple) { List<ColumnData> result = new ArrayList<>(); int i = 0; for (Object column : tuple.getColumns()) { ColumnDefinition cdef = tuple.getColumnDefinition(i); Value.Builder v = Value.newBuilder(); switch (cdef.getType().val) { case SHORT: v.setType(Type.SINT32); v.setSint32Value((Short) column); break; case DOUBLE: v.setType(Type.DOUBLE); v.setDoubleValue((Double) column); break; case BINARY: v.setType(Type.BINARY); v.setBinaryValue(ByteString.copyFrom((byte[]) column)); break; case INT: v.setType(Type.SINT32); v.setSint32Value((Integer) column); break; case TIMESTAMP: v.setType(Type.TIMESTAMP); v.setTimestampValue((Long) column); break; case ENUM: case STRING: v.setType(Type.STRING); v.setStringValue((String) column); break; case PROTOBUF: // Perhaps we could be a bit smarter here. Proto3 will have an // any-type // String messageClassname = protoType.substring(9, // protoType.length() - 1); // String schemaClassname = // messageClassname.replace("org.yamcs.protobuf.", // "org.yamcs.protobuf.Schema") + "$BuilderSchema"; MessageLite message = (MessageLite) column; v.setType(Type.BINARY); v.setBinaryValue(message.toByteString()); break; default: throw new IllegalArgumentException( "Tuple column type " + cdef.getType().val + " is currently not supported"); } ColumnData.Builder colData = ColumnData.newBuilder(); colData.setName(cdef.getName()); colData.setValue(v); result.add(colData.build()); i++; } return result; } final static Tuple toTuple(TableDefinition tblDef, List<ColumnData> columnList) { List<Object> cvalues = new ArrayList<>(); TupleDefinition tdef = new TupleDefinition(); for (ColumnData cdata : columnList) { String cname = cdata.getName(); ColumnDefinition cdef = tblDef.getColumnDefinition(cname); Object v = ValueUtility.getYarchValue(cdata.getValue()); if(cdef==null) { cdef = new ColumnDefinition(cname, DataType.typeOf(v)); } else { v = DataType.castAs(cdef.getType(), v); } tdef.addColumn(cdef); cvalues.add(v); } Tuple tuple = new Tuple(tdef, cvalues); return tuple; } final static ReplayRequest toParameterReplayRequest(RestRequest req, Parameter p, boolean descendByDefault) throws HttpException { ReplayRequest.Builder rrb = ReplayRequest.newBuilder(); rrb.setSpeed(ReplaySpeed.newBuilder().setType(ReplaySpeedType.AFAP)); IntervalResult ir = req.scanForInterval(); if (ir.hasStart()) { rrb.setStart(ir.getStart()); } if (ir.hasStop()) { rrb.setStop(ir.getStop()); } rrb.setEndAction(EndAction.QUIT); rrb.setReverse(req.asksDescending(descendByDefault)); NamedObjectId id = NamedObjectId.newBuilder().setName(p.getQualifiedName()).build(); rrb.setParameterRequest(ParameterReplayRequest.newBuilder().addNameFilter(id)); return rrb.build(); } final static TimeSeries.Sample toGPBSample(Sample sample) { TimeSeries.Sample.Builder b = TimeSeries.Sample.newBuilder(); b.setTime(TimeEncoding.toString(sample.avgt)); b.setAvg(sample.avg); b.setMin(sample.min); b.setMax(sample.max); b.setN(sample.n); return b.build(); } final static String[] EVENT_CSV_HEADER = new String[] { "Source", "Generation Time", "Reception Time", "Event Type", "Event Text" }; final static String[] tupleToCSVEvent(Tuple tuple) { Event event = tupleToEvent(tuple); return new String[] { event.getSource(), event.getGenerationTimeUTC(), event.getReceptionTimeUTC(), event.getType(), event.getMessage() }; } final static Event tupleToEvent(Tuple tuple) { Event.Builder event = Event.newBuilder((Event) tuple.getColumn("body")); event.setGenerationTimeUTC(TimeEncoding.toString(event.getGenerationTime())); event.setReceptionTimeUTC(TimeEncoding.toString(event.getReceptionTime())); return event.build(); } final static AlarmData tupleToAlarmData(Tuple tuple) { AlarmData.Builder alarmb = AlarmData.newBuilder(); alarmb.setSeqNum((int) tuple.getColumn("seqNum")); ParameterValue pval = (ParameterValue) tuple.getColumn("triggerPV"); alarmb.setTriggerValue(pval); if (tuple.hasColumn("severityIncreasedPV")) { pval = (ParameterValue) tuple.getColumn("severityIncreasedPV"); alarmb.setMostSevereValue(pval); } if (tuple.hasColumn("updatedPV")) { pval = (ParameterValue) tuple.getColumn("updatedPV"); alarmb.setCurrentValue(pval); } if (tuple.hasColumn("acknowledgedBy")) { AcknowledgeInfo.Builder ackb = AcknowledgeInfo.newBuilder(); ackb.setAcknowledgedBy((String) tuple.getColumn("acknowledgedBy")); if (tuple.hasColumn("acknowledgeMessage")) { ackb.setAcknowledgeMessage((String) tuple.getColumn("acknowledgeMessage")); } long acknowledgeTime = (Long) tuple.getColumn("acknowledgeTime"); ackb.setAcknowledgeTime(acknowledgeTime); ackb.setAcknowledgeTimeUTC(TimeEncoding.toString(acknowledgeTime)); alarmb.setAcknowledgeInfo(ackb); } return alarmb.build(); } }