Package jaron.flightgear

Source Code of jaron.flightgear.FlightGearReceiver

package jaron.flightgear;

import jaron.components.Signal;
import jaron.components.SignalListener;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;

/**
* The <code>FlightGearReceiver</code> class provides a TCP/IP connection to the
* FlightGear flight simulator (FG) via the FG generic output interface.<br>
* <code>FlightGearReceiver</code> runs as a thread and by instantiating it
* waits for the incoming connection of FG (at port {@value DEFAULT_PORT} by default).<br>
* The instantiating has to be done before FG starts up, else FG reports a
* connection error and terminates.<br>
* At the moment the <code>FlightGearReceiver</code> is limited to receiving
* numeric data.<br>
* Be aware that running FG and a Java application that uses the
* <code>FlightGearReceiver</code> needs a computer with sufficient performance.
* The consequence of a lack of performance is, that some of the data sent by FG
* could be lost because of timing issues. In this case you could run FG and the
* Java application on two different machines via a network connection.<br>
* <br>
* @author      jarontec gmail com
* @version     1.2
* @since       1.0
*/
public class FlightGearReceiver extends Thread {
  /**
   * The default update frequency of the <code>FlightGearReceiver</code>
   * is {@value DEFAULT_UPDATE_FREQUENCY}Hz.
   */
  public static final float DEFAULT_UPDATE_FREQUENCY = 10;
 
  /**
   * The default port that is used for the incoming connection. At the moment
   * this is port 5555 but this could change in the future.
   */
  public static final int DEFAULT_PORT = 5555;

  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kElevator = "controls-flight-elevator";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kAileron = "controls-flight-aileron";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kRudder = "controls-flight-rudder";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kThrottle = "controls-engines-engine-throttle";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kPitch = "orientation-pitch-deg";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kRoll = "orientation-roll-deg";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kPitchRate = "orientation-pitch-rate-degps";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kRollRate = "orientation-roll-rate-degps";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kYawRate = "orientation-yaw-rate-degps";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kAirSpeed = "velocities-airspeed-kt";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kVerticalSpeed = "velocities-vertical-speed-fps";
  /**
   * A string constant that is used to reference a FG XML ouput value.
   */
  public static final String kAltitude = "position-altitude-ft";
 
  private FlightGearParser parser = new FlightGearXMLParser();
  private HashMap<String, Signal> signals = new HashMap<String, Signal>();
  private float updateFrequency = DEFAULT_UPDATE_FREQUENCY;
  private ServerSocket server = null;
  private Socket client = null;
  private Boolean debug = false;

  /**
   * Creates a new <code>FlightGearReceiver</code> and starts a <code>Thread</code>
   * that listens for incoming connections.
   *
   * @param port  the port the receiver listens to
   */
  public FlightGearReceiver(int port) {
    // start the socket server who waits for the connecting client
    try {
      server = new ServerSocket(port); // from now on the server listens to incomming connections
    } catch (IOException e) {
      System.out.println("IOException in FlightGearReceiver(): " + e.getMessage());
    }
    setDaemon(true);
    start();
  }

  /**
   * Creates a new <code>FlightGearReceiver</code> and starts a <code>Thread</code>
   * that listens for incoming connections. It listens on the default port
   * <code>DEFAULT_PORT</code>.
   *
   * @see FlightGearReceiver#DEFAULT_PORT
   */
  public FlightGearReceiver() {
    this(DEFAULT_PORT);
  }

  /**
   * Adds a listener to a FlightGear (FG) signal that is identified by a key. The
   * key is the designator that is used in the FG configuration file for a certain
   * output data.<br>
   * In case of a change of the signal's value, all the listeners are informed
   * through the <code>EventListener</code> mechanism.<br>
   *
   * @param key         a string that identifies the FG ouput data
   * @param listener    the listener to be added
   * @see SignalListener
   */
  public void addSignalListener(String key, SignalListener listener) {
    Signal signal = signals.get(key);
    if (signal == null) signal = new Signal();
    signal.addSignalListener(listener);
    signals.put(key, signal);
  }
 
  /**
   * Disconnects the connection to the client.
   */
  private void disconnectClient() {
    try {
      if (client != null) {
        client.close();
        if (debug) System.out.println("FlightGearReceiver::disconnectClient(): Client is disconnected.");
      }
    } catch (IOException e) {
      System.out.println("IOException in FlightGearReceiver::disconnectClient(): " + e.getMessage());
    }
    finally {
      client = null;
    }
  }
 
  /**
   * Sets the update frequency for the <code>FlightGearReceiver</code>.
   * The default update frequency is set to {@value DEFAULT_UPDATE_FREQUENCY}Hz.
   *
   * @param updateFrequency the new frequency in Hz
   */
  public void setUpdateFrequency(float updateFrequency) {
    this.updateFrequency = updateFrequency;
  }
 
  /* (non-Javadoc)
   * @see java.lang.Thread#run()
   */
  @Override
  public void run() {
    while(true) {
      try {
        // check if there is a client connected to our server
        if (client != null) {
          if (debug) System.out.println("FlightGearReceiver::run(): Connection to client established, waiting for data");
          BufferedReader is = new BufferedReader(new InputStreamReader(client.getInputStream()));
          String s = is.readLine();
          // a hack to prevalidate the xml code (against timing issues)
          if(s.matches("<\\?xml.*</data>")) {
            if (parser.parse(s)) {
              // fire the signal update events
              for (String key : signals.keySet()) {
                Signal signal = signals.get(key);
                signal.setValue(parser.getDouble(key));
              }
              if (debug) System.out.println("FlightGearReceiver::run(): Data published");
            }
          }
          else {
            if (debug) System.out.println("FlightGearReceiver::run(): Data corrupted!");
          }

          if (debug) System.out.println("FlightGearReceiver::run(): Data received");
        }
        // if no client is connected then check if there is a client waiting for a connection
        else if (server != null) {
          if (debug) System.out.println("FlightGearReceiver::run(): Waiting for client");
          client = server.accept(); // waits until a connection is established
        }
      } catch (IOException e) {
          System.out.println("IOException in FlightGearReceiver::run(): " + e.getMessage());
          disconnectClient();
      }
      try { sleep((long )(1000 / updateFrequency)); } catch(InterruptedException e) {}
    }
  }

  /**
   * Sets the debugging flag which determines if the debugging informations should
   * be printed to the console. This is for debugging purpose only.
   *
   * @param debug    set to <code>true</code> if additional debugging information
   *                 should be printed
   */
  public void setDebug(Boolean debug) {
    this.debug = debug;
  }

  /**
   * Shuts this receiver down and disconnects the client.
   */
  public void shutDown() {
    disconnectClient();
    if (debug) System.out.println("FlightGearReceiver::shutDown(): Receiver is shut down.");
  }
}
TOP

Related Classes of jaron.flightgear.FlightGearReceiver

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.