package org.yamcs.parameter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.yamcs.ConfigurationException; import org.yamcs.InvalidIdentification; import org.yamcs.parameter.ParameterValue; import org.yamcs.Processor; import org.yamcs.protobuf.Yamcs.NamedObjectId; import org.yamcs.utils.LoggingUtils; import org.yamcs.xtce.Parameter; import org.yamcs.xtce.SystemParameter; import org.yamcs.xtce.XtceDb; import org.yamcs.xtceproc.XtceDbFactory; import org.yamcs.yarch.Stream; import org.yamcs.yarch.StreamSubscriber; import org.yamcs.yarch.Tuple; import org.yamcs.yarch.YarchDatabase; import com.google.common.util.concurrent.AbstractService; /** * Provides system variables from the sys_var stream to ParameterRequestManager * * It also provides some info about the current yprocessor * * For the moment all variables starting with "/yamcs" are accepted and nothing else. * Aliases are not supported. * */ public class SystemParametersProvider extends AbstractService implements StreamSubscriber, ParameterProvider { private ParameterRequestManager parameterListener; volatile private Map<String, SystemParameter> variables = new HashMap<>(); Logger log; Stream stream; XtceDb xtceDb; Processor yproc; ArrayList<ParameterValue> procParams = new ArrayList<>(); ScheduledThreadPoolExecutor timer=new ScheduledThreadPoolExecutor(1); ParameterValue procModePv; public SystemParametersProvider(String yamcsInstance) throws ConfigurationException { xtceDb = XtceDbFactory.getInstance(yamcsInstance); } @Override public void init(Processor yproc) throws ConfigurationException { String instance = yproc.getInstance(); log = LoggingUtils.getLogger(this.getClass(), yproc); YarchDatabase ydb = YarchDatabase.getInstance(instance); stream = ydb.getStream(SystemParametersCollector.STREAM_NAME); if(stream==null) { throw new ConfigurationException("Cannot find a stream named "+SystemParametersCollector.STREAM_NAME); } this.yproc = yproc; setupYProcParameters(); } @Override public void startProviding(Parameter paramDef) { //TODO } @Override public void startProvidingAll() { //TOOD } @Override public void stopProviding(Parameter paramDef) { //TODO } @Override public void onTuple(Stream s, Tuple tuple) {//the definition of the tuple is in PpProviderAdapter List<ParameterValue> params=new ArrayList<>(); for(int i=4;i<tuple.size();i++) { ParameterValue pv = (ParameterValue)tuple.getColumn(i); String name = tuple.getColumnDefinition(i).getName(); SystemParameter sv = variables.get(name); if(sv==null) { sv = (SystemParameter) xtceDb.getParameter(name); if(sv==null) { sv = createParameterForName(name); } } pv.setParameter(sv); params.add(pv); } parameterListener.update(params); } @Override public void streamClosed(Stream s) { notifyStopped(); } private synchronized SystemParameter createParameterForName(String fqname) { SystemParameter sv = variables.get(fqname); if(sv==null) { log.debug("Creating {}", fqname); sv = SystemParameter.getForFullyQualifiedName(fqname); xtceDb.addParameter(sv, true); } return sv; } /** * return true if parameter starts with "/YAMCS" or the namespace is null and the name starts with "/YAMCS" * */ @Override public boolean canProvide(NamedObjectId paraId) { return XtceDb.isSystemParameter(paraId); } @Override public boolean canProvide(Parameter para) { return para.getQualifiedName() != null && para.getQualifiedName().startsWith(XtceDb.YAMCS_SPACESYSTEM_NAME); } @Override public Parameter getParameter(NamedObjectId paraId) throws InvalidIdentification { String name = paraId.getName(); if(paraId.hasNamespace()) { name = paraId.getNamespace()+"/"+name; } return getSystemParameter(name); } /** * Get (and possibly create) system parameter. * The parameter may be in the XtceDB in case it is referred to by an algorithm. Otherwise is created on the fly and not added to XtceDB. * * @param fqname - the fully qualified name of the parameter to be returned * * @return the system parameter having the fqname. */ public SystemParameter getSystemParameter(String fqname) { SystemParameter sv = variables.get(fqname); if(sv==null) { sv = (SystemParameter) xtceDb.getParameter(fqname); if(sv==null) { sv = createParameterForName(fqname); } } return sv; } @Override public void setParameterListener(ParameterRequestManager parameterRequestManager) { this.parameterListener = parameterRequestManager; } @Override protected void doStart() { stream.addSubscriber(this); timer.scheduleAtFixedRate(()-> updateProcParameters() , 0, 1, TimeUnit.SECONDS); notifyStarted(); } @Override protected void doStop() { stream.removeSubscriber(this); timer.shutdown(); notifyStopped(); } private ParameterValue getYProcPV(String name, String value) { ParameterValue pv = new ParameterValue(getSystemParameter(XtceDb.YAMCS_SPACESYSTEM_NAME+"/yprocessor/"+name)); pv.setAcquisitionTime(yproc.getCurrentTime()); pv.setGenerationTime(yproc.getCurrentTime()); pv.setStringValue(value); return pv; } private void setupYProcParameters() { ParameterValue yprocNamePv = getYProcPV("name", yproc.getName()); procParams.add(yprocNamePv); ParameterValue yprocCreatorPv = getYProcPV("creator", yproc.getCreator()); procParams.add(yprocCreatorPv); String mode = yproc.isReplay()? "replay":"realtime"; procModePv = getYProcPV("mode", mode); procParams.add(procModePv); } private void updateProcParameters() { procModePv.setGenerationTime(yproc.getCurrentTime()); parameterListener.update(procParams); } }