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

org.yamcs.simulator.Simulator Maven / Gradle / Ivy

package org.yamcs.simulator;

import java.io.DataInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.yamcs.simulator.ui.SimWindow;

public class Simulator extends Thread {

    protected BlockingQueue pendingCommands = new ArrayBlockingQueue<>(100); // no more than 100 pending
                                                                                          // commands

    private int DEFAULT_MAX_LENGTH = 65542;
    private int maxLength = DEFAULT_MAX_LENGTH;

    private SimulationConfiguration simConfig;
    private TelemetryLink tmLink;

    private boolean isLos = false;
    private LosStore losStore;

    private SimWindow simWindow;

    private static final Logger log = LoggerFactory.getLogger(Simulator.class);

    public Simulator(SimulationConfiguration simConfig) {
        this.simConfig = simConfig;
        tmLink = new TelemetryLink(this, simConfig);
        losStore = new LosStore(this, simConfig);
    }

    @Override
    public void run() {
        for (ServerConnection serverConnection : simConfig.getServerConnections()) {
            tmLink.yamcsServerConnect(serverConnection);

            // start the TC reception thread;
            new Thread(() -> {
                while (true) {
                    try {
                        // read commands
                        CCSDSPacket packet = readPacket(
                                new DataInputStream(serverConnection.getTcSocket().getInputStream()));
                        if (packet != null)
                            pendingCommands.put(packet);

                    } catch (IOException e) {
                        serverConnection.setConnected(false);
                        tmLink.yamcsServerConnect(serverConnection);
                    } catch (InterruptedException e) {
                        log.warn("Read packets interrupted.", e);
                        Thread.currentThread().interrupt();
                    }
                }
            }).start();

            // start the TM transmission thread
            log.debug("Start TM thread");
            (new Thread(() -> tmLink.packetSend(serverConnection))).start();
        }
    }

    /**
     * this runs in a separate thread but pushes commands to the main TM thread
     */
    protected CCSDSPacket readPacket(DataInputStream dIn) {
        try {
            byte hdr[] = new byte[6];
            dIn.readFully(hdr);
            int remaining = ((hdr[4] & 0xFF) << 8) + (hdr[5] & 0xFF) + 1;
            if (remaining > maxLength - 6)
                throw new IOException("Remaining packet length too big: " + remaining + " maximum allowed is " + (maxLength - 6));
            byte[] b = new byte[6 + remaining];
            System.arraycopy(hdr, 0, b, 0, 6);
            dIn.readFully(b, 6, remaining);
            CCSDSPacket packet = new CCSDSPacket(ByteBuffer.wrap(b));
            tmLink.ackPacketSend(ackPacket(packet, 0, 0));
            return packet;

        } catch (IOException e) {
            log.error("Connection lost:" + e.getMessage(), e);
        } catch (Exception e) {
            log.error("Error reading command " + e.getMessage(), e);
        }
        return null;

    }

    public SimulationConfiguration getSimulationConfiguration() {
        return simConfig;
    }

    public LosStore getLosStore() {
        return losStore;
    }

    public boolean isLOS() {
        return isLos;
    }

    public void setLOS(boolean isLos) {
        this.isLos = isLos;
    }

    public TelemetryLink getTMLink() {
        return tmLink;
    }

    protected void transmitTM(CCSDSPacket packet) {
        tmLink.tmTransmit(packet);

    }

    protected void transmitAck(CCSDSPacket packet) {
        tmLink.tmTransmit(packet);

    }

    public void dumpLosDataFile(String filename) {
        // read data from los storage
        if (filename == null) {
            filename = losStore.getCurrentFileName();
        }
        DataInputStream dataStream = losStore.readLosFile(filename);
        if (dataStream == null)
            return;

        // TODO
        // extract packets from the data stream and put them in queue for downlink
        Queue qLosData = new ArrayBlockingQueue<>(1000);
        try {
            while (dataStream.available() > 0) {
                CCSDSPacket packet = readPacket(dataStream);
                if (packet != null) {
                    qLosData.add(packet);
                }
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        for (CCSDSPacket ccsdsPacket : qLosData) {
            for (ServerConnection serverConnection : simConfig.getServerConnections())
                serverConnection.setTmDumpPacket(ccsdsPacket);
        }

        // add packet notifying that the file has been downloaded entirely
        CCSDSPacket confirmationPacket = buildLosTransmittedRecordingPacket(filename);
        for (ServerConnection serverConnection : simConfig.getServerConnections())
            serverConnection.setTmDumpPacket(confirmationPacket);
    }

    private static CCSDSPacket buildLosTransmittedRecordingPacket(String transmittedRecordName) {
        CCSDSPacket packet = new CCSDSPacket(0, 2, 10);
        packet.appendUserDataBuffer(transmittedRecordName.getBytes());
        packet.appendUserDataBuffer(new byte[1]);

        return packet;
    }

    public void deleteLosDataFile(String filename) {
        losStore.deleteFile(filename);
        // add packet notifying that the file has been deleted
        CCSDSPacket confirmationPacket = buildLosDeletedRecordingPacket(filename);
        for (ServerConnection serverConnection : simConfig.getServerConnections())
            serverConnection.setTmDumpPacket(confirmationPacket);
    }

    private static CCSDSPacket buildLosDeletedRecordingPacket(String deletedRecordName) {
        CCSDSPacket packet = new CCSDSPacket(0, 2, 11);
        packet.appendUserDataBuffer(deletedRecordName.getBytes());
        packet.appendUserDataBuffer(new byte[1]);

        return packet;
    }

    public SimWindow getSimWindow() {
        return simWindow;
    }

    public void setSimWindow(SimWindow simWindow) {
        this.simWindow = simWindow;
    }

    public void startTriggeringLos() {
        losStore.startTriggeringLos();
    }

    public void stopTriggeringLos() {
        losStore.stopTriggeringLos();
    }

    protected CCSDSPacket ackPacket(CCSDSPacket commandPacket, int stage, int result) {
        CCSDSPacket ackPacket = new CCSDSPacket(0, commandPacket.getPacketType(), 2000);
        ackPacket.setApid(101);
        int batNum = commandPacket.getPacketId();

        ByteBuffer bb = ByteBuffer.allocate(10);

        bb.putInt(0, batNum);
        bb.putInt(4, commandPacket.getSeq());
        bb.put(8, (byte) stage);
        bb.put(9, (byte) result);

        ackPacket.appendUserDataBuffer(bb.array());

        return ackPacket;

    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy