All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.yamcs.mdb.ProcessingData Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs.mdb;

import java.util.List;
import java.util.Map;

import org.yamcs.commanding.ArgumentValue;
import org.yamcs.parameter.LastValueCache;
import org.yamcs.parameter.ParameterValue;
import org.yamcs.parameter.ParameterValueList;
import org.yamcs.parameter.RawEngValue;
import org.yamcs.parameter.Value;
import org.yamcs.xtce.Argument;
import org.yamcs.xtce.ArgumentInstanceRef;
import org.yamcs.xtce.DataSource;
import org.yamcs.xtce.DynamicIntegerValue;
import org.yamcs.xtce.Parameter;
import org.yamcs.xtce.ParameterInstanceRef;
import org.yamcs.xtce.ParameterInstanceRef.InstanceRelativeTo;
import org.yamcs.xtce.ParameterOrArgumentRef;

/**
 * This class holds live information used during a (XTCE) processing.
 * 

* It is created when data is incoming and is used in a processing pipeline. For example when a packet is received, the * following pipeline is executed: *

    *
  • a new processing data object is instantiated containing an empty parameter list and a reference to the latest * parameter value cache
  • *
  • parameters are added to it as extracted from the packet
  • *
  • calibration (raw to engineering conversion) is performed on the newly added parameters
  • *
  • algorithms are run creating new parameters also added to the processing data object
  • *
  • monitoring and generation of alarms is done for the new parameters
  • *
  • command verifiers are run (possibly creating new parameters TBD)
  • *
  • the parameter archive is populated
  • *
*

* A processing can also start when receiving command history information (used as part of command verification), when * receiving processed parameters via the pp stream or periodically by algorithms. *

* There will be different threads running in parallel, each with its own ProcessingData object but one object cannot be * shared with another thread. * *

* The following data is part of this object: *

    *
  • tmParamsCache - stores the latest values of the "released" TM parameters from a processor (processor's * lastValueCache). Data can be updated from outside of this processing thread. The cache will buffer older values for * some parameters if required (for example algorithms or match criteria can require old instances of parameter * values).
  • *
  • tmParams - stores the "current" delivery - parameters that are being produced during the current pipeline * execution. This list will only modify from within the pipeline (and is not visible outside) and all the data here is * considered "more recent" than the data from the tmParamsCache. At the end of the execution of the pipeline, the data * is moved from here to the tmParamsCache (i.e the processor lastValueCache)
  • *
  • cmdArgs - if the processing is part of a command, this stores the arguments of the command. Otherwise it is null. * The command arguments are not modified during the pipeline execution.
  • *
  • cmdParamsCache - this is similar with the tmParams but stores parameters that are contextualized to the command. * This includes command properties and command history parameters. The list can modify from outside the pipeline.
  • *
  • cmdParams - stores the "current" delivery command parameters. It is initialised when command history information * is received. New elements can be added by algorithms producing command parameter values. A command parameter is one * whose datasource is {@link DataSource#COMMAND}. *
* * */ public class ProcessingData { final protected LastValueCache tmParamsCache; final protected ParameterValueList tmParams; final protected Map cmdArgs; final protected LastValueCache cmdParamsCache; final protected ParameterValueList cmdParams; /** * Used in a TM processing pipeline - for example when a TM packet is received */ public static ProcessingData createForTmProcessing(LastValueCache tmValueCache) { return new ProcessingData(tmValueCache, new ParameterValueList(), null, null, null); } /** * Used in TC processing when command history events are received, they will be added to the cmdParams. */ public static ProcessingData createForCmdProcessing(LastValueCache tmValueCache, Map arguments, LastValueCache cmdLastValueCache) { return new ProcessingData(tmValueCache, new ParameterValueList(), arguments, cmdLastValueCache, new ParameterValueList()); } /** * Processing data which contains values to be used in algorithm initialisation. *

* The tmParams and cmdParams will be null. */ public static ProcessingData createInitial(LastValueCache tmParamsCache, Map arguments, LastValueCache cmdParamsCache) { return new ProcessingData(tmParamsCache, null, arguments, cmdParamsCache, null); } /** * Create a new processing data object with the tmParamsCache and tmParams shared with the data object, but with new * cmdParams. To be used in command verifiers - each command has its own context with different cmdParams. *

* It is used when starting a command processing chain. */ public static ProcessingData cloneForCommanding(ProcessingData data, Map arguments, LastValueCache cmdParams) { return new ProcessingData(data.tmParamsCache, data.tmParams, arguments, cmdParams, new ParameterValueList()); } /** * keeps the tmParamsCache and tmParams from the given data */ public static ProcessingData cloneForTm(ProcessingData data) { return new ProcessingData(data.tmParamsCache, data.tmParams, null, null, null); } /** * creates an object with an empty cache and with the given values as current tm delivery. Used in unit tests */ public static ProcessingData createForTestTm(ParameterValue... pvlist) { ProcessingData data = new ProcessingData(new LastValueCache(), new ParameterValueList(), null, null, null); for (ParameterValue pv : pvlist) { data.addTmParam(pv); } return data; } /** * same as above but creates command parameters */ public static ProcessingData createForTestCmd(ParameterValue... pvlist) { ProcessingData data = new ProcessingData(new LastValueCache(), null, null, new LastValueCache(), new ParameterValueList()); for (ParameterValue pv : pvlist) { data.addCmdParam(pv); } return data; } public ProcessingData(LastValueCache lastValueCache, ParameterValueList tmParams, Map cmdArgs, LastValueCache cmdParamsCache, ParameterValueList cmdParams) { this.tmParams = tmParams; this.tmParamsCache = lastValueCache; this.cmdArgs = cmdArgs; this.cmdParams = cmdParams; this.cmdParamsCache = cmdParamsCache; } public ParameterValueList getTmParams() { return tmParams; } public void addTmParam(ParameterValue pv) { tmParams.add(pv); } public void addTmParams(List params) { tmParams.addAll(params); } public void addCmdParam(ParameterValue pv) { cmdParams.add(pv); } /** * Returns a parameter value associated to the parameter reference or null if none is found. *

* The instance is according to XTCE rules: if tmParams/cmdParams contains multiple values for the parameter, then * the oldest one (first inserted in the list) is instance 0, the next one is instance 1, etc. *

* The negative instances are retrieved from the cache: -1 is the latest value in tmParamsCache (the one which was * added last), -2 is the previous one and so on. * *

* If {@code allowOld = true} and the tmParams/cmdParams does not contain a value for the parameter, then the * instances in the cache are counted down from 0 instead of -1. *

* If {@code allowOld = false}, the return will always be null if the tmParams/cmdParams does not contain a value * for the parameter. * */ public ParameterValue getParameterInstance(ParameterInstanceRef pref) { Parameter param = pref.getParameter(); if (param.isCommandParameter()) { return get(cmdParams, cmdParamsCache, param, pref.getInstance(), pref.getRelativeTo()); } else { return get(tmParams, tmParamsCache, param, pref.getInstance(), pref.getRelativeTo()); } } private static ParameterValue get(ParameterValueList params, LastValueCache paramsCache, Parameter param, int instance, InstanceRelativeTo instanceRelativeTo) { switch (instanceRelativeTo) { case CURRENT_ENTRY_WITHIN_PACKET -> { // paramsCache not considered if (params == null) { return null; } return params.getFromEnd(param, -instance); } case CURRENT_ENTRY_ACROSS_PACKETS -> { int n = -instance; if (params != null) { var pv = params.getFromEnd(param, n); if (pv != null) { return pv; } n -= params.count(param); } if (paramsCache == null) { return null; } return paramsCache.getValueFromEnd(param, n); } case PACKET_START_WITHIN_PACKET -> { // paramsCache is not considered if (params == null || instance < 0) { return null; } return params.get(param, instance); } case PACKET_START_ACROSS_PACKETS -> { // this is from Yamcs before 5.10.4 if (params == null || params.getFirstInserted(param) == null) { if (paramsCache == null || instance > 0) { return null; } return paramsCache.getValueFromEnd(param, -instance); } else { if (instance >= 0) { return params.get(param, instance); } else { return paramsCache.getValueFromEnd(param, -instance - 1); } } } default -> throw new IllegalStateException("Unknown " + instanceRelativeTo); } } public ArgumentValue getCmdArgument(Argument arg) { return (cmdArgs == null) ? null : cmdArgs.get(arg); } public Map getCmdArgs() { return cmdArgs; } /** * Returns true if the {@code tmParams} or {@code cmdParams} contains a value for {@code param} */ public boolean containsUpdate(Parameter param) { if (param.isCommandParameter()) { return cmdParams != null && cmdParams.getFirstInserted(param) != null; } else { return tmParams != null && tmParams.getFirstInserted(param) != null; } } public ParameterValueList getCmdParams() { return cmdParams; } public long resolveDynamicIntegerValue(DynamicIntegerValue div) throws XtceProcessingException { ParameterOrArgumentRef ref = div.getDynamicInstanceRef(); RawEngValue pv = null; if (ref instanceof ParameterInstanceRef) { pv = getParameterInstance((ParameterInstanceRef) ref); } else if (ref instanceof ArgumentInstanceRef) { ArgumentInstanceRef argRef = (ArgumentInstanceRef) ref; Argument arg = cmdArgs.keySet().stream().filter(a -> a.getName().equals(argRef.getName())).findFirst() .orElse(null); if (arg == null) { throw new XtceProcessingException("Missing argument for dynamic integer value: " + ref.getName()); } pv = cmdArgs.get(arg); } if (pv == null) { throw new XtceProcessingException("Missing value for dynamic integer value: " + ref.getName()); } Value value = ref.useCalibratedValue() ? pv.getEngValue() : pv.getRawValue(); if (value == null) { throw new XtceProcessingException("Missing " + (ref.useCalibratedValue() ? "engineering" : "raw") + " value for dynamic size in bits parameter: " + ref.getName()); } try { return div.transform(value.toLong()); } catch (UnsupportedOperationException e) { throw new XtceProcessingException("Cannot interpret value of type " + value.getClass() + " as integer; used in the dynamic value specification"); } } @Override public String toString() { return "EvaluatorInput [params=" + tmParams + ", cmdArgs=" + ((cmdArgs == null) ? null : cmdArgs.values()) + ", cmdParams=" + cmdParams + ", cmdParamsCache=" + cmdParamsCache + "]"; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy