package org.yamcs.commanding; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; import org.yamcs.protobuf.Commanding.CommandHistoryAttribute; import org.yamcs.protobuf.Commanding.CommandHistoryEntry; import org.yamcs.protobuf.Commanding.CommandId; import org.yamcs.protobuf.ValueHelper; import org.yamcs.protobuf.Yamcs.Value.Type; import org.yamcs.parameter.Value; import org.yamcs.tctm.TcUplinkerAdapter; import org.yamcs.utils.ValueUtility; import org.yamcs.xtce.Argument; import org.yamcs.xtce.MetaCommand; import org.yamcs.yarch.ColumnDefinition; import org.yamcs.yarch.DataType; import org.yamcs.yarch.Tuple; import org.yamcs.yarch.TupleDefinition; /** * This class is to keep track of a command binary and source included * @author nm * */ public class PreparedCommand { private byte[] binary; private CommandId id; private MetaCommand metaCommand; private final UUID uuid; // Used in REST API as an easier single-field ID. Not persisted. //used when a command has a transmissionConstraint with timeout // when the command is ready to go, but is waiting for a transmission constraint, this is set to true private boolean pendingTransmissionConstraint; // this is the time when the clock starts ticking for fullfilling the transmission constraint // -1 means it has not been set yet private long transmissionContraintCheckStart = -1; List<CommandHistoryAttribute> attributes=new ArrayList<>(); private Map<Argument, Value> argAssignment; //column names to use when converting to tuple public final static String CNAME_GENTIME = "gentime"; public final static String CNAME_SEQNUM = "seqNum"; public final static String CNAME_ORIGIN = "origin"; public final static String CNAME_USERNAME = "username"; public final static String CNAME_BINARY = "binary"; public final static String CNAME_CMDNAME = "cmdName"; public final static String CNAME_SOURCE = "source"; public PreparedCommand(CommandId id) { this.id=id; uuid=UUID.randomUUID(); } /** * Used for testing the uplinkers * @param binary */ public PreparedCommand(byte[] binary) { this.setBinary(binary); uuid=UUID.randomUUID(); } public long getGenerationTime() { return id.getGenerationTime(); } public void setSource(String source) { setStringAttribute(CNAME_SOURCE, source); } public String getSource() { return getStringAttribute(CNAME_SOURCE); } public String getCmdName() { return id.getCommandName(); } public String getStringAttribute(String attrname) { CommandHistoryAttribute a=getAttribute(attrname); Value v = ValueUtility.fromGpb(a.getValue()); if((a!=null) && (v.getType()==Type.STRING)) return v.getStringValue(); return null; } public CommandHistoryAttribute getAttribute(String name) { for(CommandHistoryAttribute a:attributes) { if(name.equals(a.getName())) return a; } return null; } public CommandId getCommandId() { return id; } public UUID getUUID() { return uuid; } static public CommandId getCommandId(Tuple t) { CommandId cmdId=CommandId.newBuilder() .setGenerationTime((Long)t.getColumn(CNAME_GENTIME)) .setOrigin((String)t.getColumn(CNAME_ORIGIN)) .setSequenceNumber((Integer)t.getColumn(CNAME_SEQNUM)) .setCommandName((String)t.getColumn(CNAME_CMDNAME)) .build(); return cmdId; } public Tuple toTuple() { TupleDefinition td=TcUplinkerAdapter.TC_TUPLE_DEFINITION.copy(); ArrayList<Object> al=new ArrayList<Object>(); al.add(id.getGenerationTime()); al.add(id.getOrigin()); al.add(id.getSequenceNumber()); al.add(id.getCommandName()); if(getBinary()!=null) { td.addColumn(CNAME_BINARY, DataType.BINARY); al.add(getBinary()); } for(CommandHistoryAttribute a:attributes) { td.addColumn(a.getName(), ValueUtility.getYarchType(a.getValue().getType())); al.add(ValueUtility.getYarchValue(a.getValue())); } Tuple t = new Tuple(td, al.toArray()); return t; } public void setBinary(byte[] b) { this.binary =b; } public String getUsername() { CommandHistoryAttribute cha = getAttribute(CNAME_USERNAME); if(cha==null) return null; return cha.getValue().getStringValue(); } public List<CommandHistoryAttribute> getAttributes() { return attributes; } public static PreparedCommand fromTuple(Tuple t) { CommandId cmdId = getCommandId(t); PreparedCommand pc=new PreparedCommand(cmdId); for(int i=0;i<t.size();i++) { ColumnDefinition cd=t.getColumnDefinition(i); String name=cd.getName(); Value v = ValueUtility.getColumnValue(cd, t.getColumn(i)); if(CNAME_GENTIME.equals(name) || CNAME_ORIGIN.equals(name) || CNAME_SEQNUM.equals(name)) continue; CommandHistoryAttribute a=CommandHistoryAttribute.newBuilder() .setName(name) .setValue(ValueUtility.toGbp(v)) .build(); pc.attributes.add(a); } pc.setBinary((byte[])t.getColumn(CNAME_BINARY)); return pc; } public static PreparedCommand fromCommandHistoryEntry(CommandHistoryEntry che) { CommandId cmdId = che.getCommandId(); PreparedCommand pc = new PreparedCommand(cmdId); pc.attributes = che.getAttrList(); return pc; } public CommandHistoryEntry toCommandHistoryEntry() { CommandHistoryEntry.Builder cheb = CommandHistoryEntry.newBuilder().setCommandId(id); cheb.addAllAttr(attributes); return cheb.build(); } public void setStringAttribute(String name, String value) { int i; for(i =0; i<attributes.size(); i++) { CommandHistoryAttribute a = attributes.get(i); if(name.equals(a.getName())) break; } CommandHistoryAttribute a=CommandHistoryAttribute.newBuilder() .setName(name) .setValue(ValueHelper.newValue(value)) .build(); if(i<attributes.size()) { attributes.set(i, a); } else { attributes.add(a); } } public void addStringAttribute(String name, String value) { CommandHistoryAttribute a=CommandHistoryAttribute.newBuilder() .setName(name) .setValue(ValueHelper.newValue(value)) .build(); attributes.add(a); } public void addAttribute(CommandHistoryAttribute cha) { attributes.add(cha); } public byte[] getBinary() { return binary; } public void setUsername(String username) { setStringAttribute(CNAME_USERNAME, username); } public MetaCommand getMetaCommand() { return metaCommand; } public void setMetaCommand(MetaCommand cmd) { this.metaCommand = cmd; } public boolean isPendingTransmissionConstraints() { return pendingTransmissionConstraint; } public void setPendingTransmissionConstraints(boolean b) { this.pendingTransmissionConstraint = b; } public long getTransmissionContraintCheckStart() { return transmissionContraintCheckStart; } public void setTransmissionContraintCheckStart(long transmissionContraintCheckStart) { this.transmissionContraintCheckStart = transmissionContraintCheckStart; } public void setArgAssignment(Map<Argument, Value> argAssignment) { this.argAssignment = argAssignment; } public Map<Argument, Value> getArgAssignment() { return argAssignment; } }