package org.yamcs.tctm;
import java.io.IOException;
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.cmdhistory.YarchCommandHistoryAdapter;
import org.yamcs.commanding.PreparedCommand;
import org.yamcs.management.ManagementService;
import org.yamcs.utils.YObjectLoader;
import org.yamcs.yarch.DataType;
import org.yamcs.yarch.Stream;
import org.yamcs.yarch.StreamSubscriber;
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;
import org.yamcs.api.YamcsApiException;
/**
* Sends commands from the yarch stream to a {@link org.yamcs.tctm.TcUplinker }
*
*/
public class TcUplinkerAdapter extends AbstractService {
private Collection<TcDataLink> tcuplinkers=new ArrayList<TcDataLink>();
final String yamcsInstance;
final static public String KEY_tcDataLinks = "tcDataLinks";
final static public String KEY_tcUplinkers = "tcUplinkers";
final static public String CMDHIST_TUPLE_COL_CMDNAME = "cmdName";
static public final TupleDefinition TC_TUPLE_DEFINITION=new TupleDefinition();
//this is the commandId (used as the primary key when recording), the rest will be handled dynamically
static {
TC_TUPLE_DEFINITION.addColumn("gentime", DataType.TIMESTAMP);
TC_TUPLE_DEFINITION.addColumn("origin", DataType.STRING);
TC_TUPLE_DEFINITION.addColumn("seqNum", DataType.INT);
TC_TUPLE_DEFINITION.addColumn(CMDHIST_TUPLE_COL_CMDNAME, DataType.STRING);
}
static public final String REALTIME_TC_STREAM_NAME="tc_realtime";
@SuppressWarnings({ "rawtypes", "static-access", "unchecked" })
public TcUplinkerAdapter(String yamcsInstance) throws ConfigurationException, StreamSqlException, ParseException, YamcsApiException, IOException {
this.yamcsInstance=yamcsInstance;
YarchDatabase ydb=YarchDatabase.getInstance(yamcsInstance);
//new StreamAdapter(realtimeStream, new SimpleString(archiveInstance+".tc.realtime"), new TmTupleTranslator());
YConfiguration c = YConfiguration.getConfiguration("yamcs."+yamcsInstance);
List uplinkers = c.containsKey(KEY_tcDataLinks)?c.getList(KEY_tcDataLinks):c.getList(KEY_tcUplinkers);
int count=1;
for(Object o:uplinkers) {
if(!(o instanceof Map)) throw new ConfigurationException("uplinker has to be Map and not a "+o.getClass());
Map m=(Map)o;
String className=c.getString(m, "class");
Object args=null;
if(m.containsKey("args")) {
args=m.get("args");
} else if(m.containsKey("spec")) {
args=m.get("spec");
}
String streamName=c.getString(m, "stream");
boolean enabledAtStartup=true;
if(m.containsKey("enabledAtStartup")) {
enabledAtStartup=c.getBoolean(m, "enabledAtStartup");
}
final Stream stream;
String name = "tc"+count;
if(m.containsKey("name")) {
name=m.get("name").toString();
}
if(streamName==null) {
streamName = REALTIME_TC_STREAM_NAME;
}
stream = ydb.getStream(streamName);
if(stream==null) throw new ConfigurationException("Cannot find stream '"+streamName+"'");
YObjectLoader<TcDataLink> objloader=new YObjectLoader<TcDataLink>();
final TcDataLink tcuplinker = (args==null)?objloader.loadObject(className, yamcsInstance, name): objloader.loadObject(className, yamcsInstance, name, args);
if(!enabledAtStartup) tcuplinker.disable();
stream.addSubscriber(new StreamSubscriber() {
@Override
public void onTuple(Stream s, Tuple tuple) {
tcuplinker.sendTc(PreparedCommand.fromTuple(tuple));
}
@Override
public void streamClosed(Stream s) {
stopAsync();
}
});
tcuplinker.setCommandHistoryPublisher(new YarchCommandHistoryAdapter(yamcsInstance));
tcuplinkers.add(tcuplinker);
ManagementService.getInstance().registerLink(yamcsInstance, name, streamName, args!=null?args.toString():"", tcuplinker);
count++;
}
}
@Override
protected void doStart() {
for(TcDataLink tcuplinker:tcuplinkers) {
tcuplinker.startAsync();
}
notifyStarted();
}
@Override
protected void doStop() {
for(TcDataLink tcuplinker:tcuplinkers) {
tcuplinker.stopAsync();
}
notifyStopped();
}
}