package org.yamcs.tctm; import java.io.IOException; import java.nio.ByteBuffer; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import org.yamcs.ConfigurationException; import org.yamcs.YConfiguration; import org.yamcs.api.YamcsApiException; import org.yamcs.archive.PacketWithTime; import org.yamcs.management.ManagementService; import org.yamcs.utils.YObjectLoader; import org.yamcs.yarch.DataType; import org.yamcs.yarch.Stream; import org.yamcs.yarch.Tuple; import org.yamcs.yarch.TupleDefinition; import org.yamcs.yarch.YarchDatabase; import org.yamcs.yarch.streamsql.ParseException; import org.yamcs.yarch.streamsql.StreamSqlException; import com.google.common.util.concurrent.AbstractService; /** * Loads multiple TmPacketSource and inject all the packets into a defined stream * @author nm * */ public class TmDataLinkInitialiser extends AbstractService { final static public String KEY_tmProviders = "tmProviders"; final static public String KEY_tmDataLinks = "tmDataLinks"; private Collection<TmPacketDataLink> tmproviders=new ArrayList<TmPacketDataLink>(); final String yamcsInstance; final static public String GENTIME_COLUMN = "gentime"; final static public String SEQNUM_COLUMN = "seqNum"; final static public String RECTIME_COLUMN = "rectime"; final static public String PACKET_COLUMN = "packet"; static public final TupleDefinition TM_TUPLE_DEFINITION=new TupleDefinition(); static { TM_TUPLE_DEFINITION.addColumn(GENTIME_COLUMN, DataType.TIMESTAMP); TM_TUPLE_DEFINITION.addColumn(SEQNUM_COLUMN, DataType.INT); TM_TUPLE_DEFINITION.addColumn(RECTIME_COLUMN, DataType.TIMESTAMP); //reception or recording time (useful in case we import data from other recordings which provide this) TM_TUPLE_DEFINITION.addColumn(PACKET_COLUMN, DataType.BINARY); } @SuppressWarnings({ "unchecked", "rawtypes" }) public TmDataLinkInitialiser(String yamcsInstance) throws ConfigurationException, IOException { this.yamcsInstance = yamcsInstance; YarchDatabase ydb = YarchDatabase.getInstance(yamcsInstance); YConfiguration c = YConfiguration.getConfiguration("yamcs."+yamcsInstance); List providers = c.containsKey(KEY_tmDataLinks)?c.getList(KEY_tmDataLinks):c.getList(KEY_tmProviders); int count=1; for(Object o:providers) { if(!(o instanceof Map<?, ?>)) throw new ConfigurationException("tmProvider has to be a Map and not a "+o.getClass()); Map<String, Object> m=(Map<String, Object>)o; String className=YConfiguration.getString(m, "class"); Object args=null; if(m.containsKey("args")) { args=m.get("args"); } else if(m.containsKey("spec")) { args=m.get("spec"); } String name="tm"+count; if(m.containsKey("name")) { name=m.get("name").toString(); } boolean enabledAtStartup=true; if(m.containsKey("enabledAtStartup")) { enabledAtStartup=YConfiguration.getBoolean(m, "enabledAtStartup"); } String streamName=YConfiguration.getString(m, "stream"); Stream s=ydb.getStream(streamName); if(s==null) { throw new ConfigurationException("Cannot find stream '"+streamName+"'"); } final Stream stream=s; YObjectLoader<TmPacketDataLink> objloader=new YObjectLoader<TmPacketDataLink>(); TmPacketDataLink prov= null; if(args!=null) { prov = objloader.loadObject(className, yamcsInstance, name, args); } else { prov = objloader.loadObject(className, yamcsInstance, name); } if(!enabledAtStartup) prov.disable(); prov.setTmSink(new TmSink() { @Override public void processPacket(PacketWithTime pwrt) { long time= pwrt.getGenerationTime(); byte[] pkt = pwrt.getPacket(); int apidSeqCount = ByteBuffer.wrap(pkt).getInt(0); Tuple t=new Tuple(TM_TUPLE_DEFINITION, new Object[] {time, apidSeqCount, pwrt.rectime, pkt }); stream.emitTuple(t); } }); tmproviders.add(prov); ManagementService.getInstance().registerLink(yamcsInstance, name, streamName, args!=null?args.toString():"", prov); count++; } } @Override protected void doStart() { for(TmPacketDataLink prov:tmproviders) { prov.startAsync(); } notifyStarted(); } @Override protected void doStop() { for(TmPacketDataLink prov:tmproviders) { prov.stopAsync(); } notifyStopped(); } }