package org.yamcs.commanding;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.parameter.ParameterValue;
import org.yamcs.parameter.Value;
import org.yamcs.Processor;
import org.yamcs.algorithms.AlgorithmExecListener;
import org.yamcs.algorithms.AlgorithmExecutionContext;
import org.yamcs.algorithms.AlgorithmManager;
import org.yamcs.cmdhistory.CommandHistoryConsumer;
import org.yamcs.commanding.CommandVerificationHandler.VerifResult;
import org.yamcs.protobuf.Commanding.CommandHistoryAttribute;
import org.yamcs.protobuf.Commanding.CommandId;
import org.yamcs.utils.ValueUtility;
import org.yamcs.xtce.Algorithm;
import org.yamcs.xtce.Argument;
import org.yamcs.xtce.CommandVerifier;
import org.yamcs.xtce.Parameter;
import org.yamcs.xtce.XtceDb;
public class AlgorithmVerifier extends Verifier implements AlgorithmExecListener, CommandHistoryConsumer {
final Algorithm alg;
final AlgorithmExecutionContext algCtx;
final PreparedCommand pc;
Logger log;
final XtceDb xtcedb;
final Processor yproc;
AlgorithmVerifier(CommandVerificationHandler cvh, CommandVerifier cv) {
super(cvh, cv);
alg = cv.getAlgorithm();
algCtx= cvh.getAlgorithmExecutionContext();
pc = cvh.getPreparedCommand();
yproc = cvh.getProcessor();
xtcedb = yproc.getXtceDb();
log=LoggerFactory.getLogger(AlgorithmVerifier.class);
}
@Override
void start() {
log.debug("Starting verifier "+cv.getStage()+" with the algorithm "+alg.getName());
//push all the command information as parameters
List<ParameterValue> pvList = new ArrayList<>();
for(CommandHistoryAttribute cha: pc.getAttributes()) {
String fqn = XtceDb.YAMCS_CMD_SPACESYSTEM_NAME+"/"+cha.getName();
if(xtcedb.getParameter(fqn)==null) {
//if it was required in the algorithm, it would be already in the system parameter db
log.debug("Not adding {} to the context parameter list because it is not defined in the XtceDb", fqn);
continue;
}
Parameter p = xtcedb.getParameter(fqn);
ParameterValue pv = new ParameterValue(p);
pv.setEngineeringValue(ValueUtility.fromGpb(cha.getValue()));
pvList.add(pv);
}
Map<Argument, Value> argAssignment = pc.getArgAssignment();
for(Map.Entry<Argument, Value> e: argAssignment.entrySet()) {
String fqn = XtceDb.YAMCS_CMD_SPACESYSTEM_NAME+"/arg/"+e.getKey().getName();
if(xtcedb.getParameter(fqn)==null) {
//if it was required in the algorithm, it would be already in the SystemParameterdb
log.debug("Not adding {} to the context parameter list because it is not defined in the XtceDb", fqn);
continue;
}
Parameter p = xtcedb.getParameter(fqn);
ParameterValue pv = new ParameterValue(p);
pv.setEngineeringValue(e.getValue());
pvList.add(pv);
}
if(pvList.isEmpty()) {
log.debug("No CMD information PV to be sent to the Algorithm");
} else {
AlgorithmManager algMgr = cvh.getAlgorithmManager();
algMgr.activateAlgorithm(alg, algCtx, this);
algMgr.updateParameters(pvList, algCtx);
}
try {
yproc.getCommandHistoryManager().subscribeCommand(pc.getCommandId(), this);
} catch (InvalidCommandId e) {
log.error("Got invalidCommand id while subscribing for command history", e);
}
}
@Override
public void algorithmRun(Object returnValue, List<ParameterValue> outputValues) {
if(returnValue==null) {
log.trace("Algorithm {} run but did not return a result.", alg.getName());
return;
}
if(!(returnValue instanceof Boolean)) {
log.warn("Algorithm {} run but returned a {} instead of a Boolean", alg.getName(), returnValue.getClass());
return;
}
boolean r = (Boolean) returnValue;
AlgorithmManager algMgr = cvh.getAlgorithmManager();
algMgr.deactivateAlgorithm(alg, algCtx);
yproc.getCommandHistoryManager().unsubscribeCommand(pc.getCommandId(), this);
cvh.onVerifierFinished(this, r?VerifResult.OK:VerifResult.NOK);
}
@Override
public void addedCommand(PreparedCommand pc) {} //this will not be called because we subscribe to only one command
//called from the command history when things are added in the stream
@Override
public void updatedCommand(CommandId cmdId, long changeDate, String key, Value value) {
String fqn = XtceDb.YAMCS_CMDHIST_SPACESYSTEM_NAME+"/"+key;
if(xtcedb.getParameter(fqn)==null) {
//if it was required in the algorithm, it would be in the SystemParameterDb
log.debug("Not adding {} to the context parameter list because it is not defined in the XtceDb", fqn);
} else {
Parameter p = xtcedb.getParameter(fqn);
ParameterValue pv = new ParameterValue(p);
pv.setEngineeringValue(value);
AlgorithmManager algMgr = cvh.getAlgorithmManager();
algMgr.updateParameters(Arrays.asList(pv), algCtx);
}
}
}