mirror of
https://github.com/nasa/fprime.git
synced 2025-12-10 17:47:10 -06:00
288 lines
11 KiB
Python
Executable File
288 lines
11 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# encoding: utf-8
|
|
'''
|
|
This is the f prime ground support equipment client
|
|
program. It is designed to bring up a front end
|
|
GUI sending commands and receiving telemetry that
|
|
are defined utilizing the various XML files
|
|
used by the Autocoder to generate framework codes.
|
|
|
|
@author: Leonard J. Reder
|
|
|
|
@copyright: 2014 California Institute of Technology. All rights reserved.
|
|
|
|
@license: license
|
|
|
|
@contact: reder@jpl.nasa.gov
|
|
'''
|
|
import sys
|
|
import os
|
|
import Tkinter
|
|
import Pmw
|
|
import time
|
|
import glob
|
|
import random
|
|
from fprime.gse.utils import Logger
|
|
from fprime.gse.utils import PortFinder
|
|
from fprime.gse.utils import ConfigManager
|
|
|
|
import fprime.gse.controllers.exceptions
|
|
import traceback
|
|
|
|
from fprime.gse.views import main_panel_factory
|
|
from fprime.gse.views import main_panel
|
|
from optparse import OptionParser
|
|
|
|
__all__ = []
|
|
__version__ = 0.1
|
|
__date__ = '2015-04-03'
|
|
__updated__ = '2015-04-03'
|
|
LOGGER = None
|
|
|
|
def connect(opts):
|
|
"""
|
|
Routine to launch Threaded TCP Server
|
|
and connect to gse.py. The routine
|
|
creates default log files of stdout
|
|
and stderr.
|
|
"""
|
|
main_panel.TopPanel(None, None, opts).startTCP()
|
|
|
|
|
|
def execute(opts):
|
|
"""
|
|
Routine to launch a FSW binary that
|
|
must be specified on the command line.
|
|
The routine creates default log files
|
|
of stdout and stderr.
|
|
"""
|
|
#
|
|
# Setup log file name here...
|
|
#
|
|
if opts == None:
|
|
p = os.environ['HOME'] + os.sep + 'fprime_logs' + os.sep + "app"
|
|
else:
|
|
p = opts.log_file_path + os.sep + "app"
|
|
#
|
|
if not os.path.exists(p):
|
|
os.makedirs(p)
|
|
#
|
|
logfile = p + os.sep + time.strftime("%y%m%d%H%M%S", time.gmtime()) + '_GSE.log'
|
|
#
|
|
# Launch the FSW application saving both stdout and stdin to common log.
|
|
#
|
|
op_sys = os.uname()[0]
|
|
if 'BUILD_ROOT' in os.environ:
|
|
build_root_path = os.environ['BUILD_ROOT']
|
|
else:
|
|
print "EXCEPTIONS: BUILD_ROOT Environment Variable not found!"
|
|
raise exceptions.EnvironmentError
|
|
|
|
app_cmd = "\"%s -p %s | tee -a %s; exit\"" % (opts.exec_app, opts.port, logfile)
|
|
#app_cmd = "\"%s |& tee -a %s; exit\"" % (opts.exec_app, logfile)
|
|
#app_cmd = "\"%s\"" % (opts.exec_app)
|
|
if op_sys == 'Darwin':
|
|
app_script = '/usr/bin/osascript '
|
|
app_args = '-e \'tell application \"Terminal" to do script '
|
|
# Note the exit is so Mac Terminal.app window will exit when process killed...
|
|
cmd = app_script + app_args + app_cmd + " \'"
|
|
else:
|
|
app_script = "/usr/bin/gnome-terminal"
|
|
#app_args = "-e "
|
|
app_args = " -e"
|
|
cmd = app_script + app_args + app_cmd
|
|
os.system(cmd)
|
|
LOGGER.info("FSW Application Started: %s" % opts.exec_app)
|
|
|
|
def set_pmw_about_info():
|
|
config_manager = ConfigManager.ConfigManager.getInstance()
|
|
## Program Information
|
|
version_str = config_manager.get('about_info', 'version_number') + '\n' + config_manager.get('about_info', 'version_date')
|
|
version_str += '\n' + config_manager.get('about_info', 'last_modified') + '\n'
|
|
Pmw.aboutversion(version_str)
|
|
Pmw.aboutcopyright(config_manager.get('about_info', 'copyright'))
|
|
Pmw.aboutcontact(config_manager.get('about_info', 'contact'))
|
|
|
|
def main_window_start(opts):
|
|
"""
|
|
Everything GUI gets started from this routine.
|
|
"""
|
|
root = Tkinter.Tk()
|
|
#root.option_readfile('optionDB')
|
|
Pmw.initialise()
|
|
set_pmw_about_info()
|
|
|
|
mpf = main_panel_factory.MainPanelFactory(opts)
|
|
mpf.create(root)
|
|
|
|
if opts.no_about == False:
|
|
# Show about window
|
|
config_manager = ConfigManager.ConfigManager.getInstance()
|
|
a = Pmw.AboutDialog(root, applicationname=config_manager.get('about_info', 'app_name'))
|
|
a.show()
|
|
|
|
|
|
# This is a quick fix since something
|
|
# locks the main window event loop.
|
|
w = Tkinter.Toplevel()
|
|
w.destroy()
|
|
|
|
root.update()
|
|
return root
|
|
|
|
|
|
def main(argv=None):
|
|
'''
|
|
Command line options.
|
|
'''
|
|
global LOGGER
|
|
#
|
|
program_name = os.path.basename(sys.argv[0])
|
|
program_version = "v0.1"
|
|
program_build_date = "%s" % __updated__
|
|
|
|
program_version_string = '%%prog %s (%s)' % (program_version, program_build_date)
|
|
#program_usage = '''usage: spam two eggs''' # optional - will be autogenerated by optparse
|
|
program_longdesc = '''''' # optional - give further explanation about what the program does
|
|
program_license = "Copyright 2015 user_name (California Institute of Technology) \
|
|
ALL RIGHTS RESERVED. U.S. Government Sponsorship acknowledged."
|
|
|
|
|
|
|
|
|
|
if argv is None:
|
|
argv = sys.argv[1:]
|
|
try:
|
|
|
|
# Get ConfigManager
|
|
config_manager = ConfigManager.ConfigManager.getInstance()
|
|
# Set default values
|
|
generated_path = config_manager.get("filepaths", "generated_path")
|
|
log_file_path = config_manager.get("filepaths", "log_file_path")
|
|
|
|
fsw_app = None
|
|
|
|
#
|
|
# setup option parser
|
|
parser = OptionParser(version=program_version_string, epilog=program_longdesc, description=program_license)
|
|
parser.add_option("-d", "--dictionary", dest="generated_path", action="store", type="string", \
|
|
help="Set base path to generated command/telemetry definition files [default: %default]", \
|
|
default=generated_path)
|
|
parser.add_option("-a", "--addr", dest="addr", action="store", type="string", help="set threaded tcp socket server address [default: %default]", \
|
|
default="127.0.0.1")
|
|
parser.add_option("-c", "--connect", action="store_true", dest="connect", help="Launches the Threaded TCP Socket Server on startup and connect to it [default: %default]", \
|
|
default=False)
|
|
parser.add_option("-p", "--port", dest="port", action="store", type="int", help="Set threaded tcp socket server port [default: %default]", \
|
|
#default=50007)
|
|
#default=PortFinder.old_getport(50000,[]))
|
|
)
|
|
parser.add_option("-s", "--stream_port", dest="stream_port", action="store", type="int", help="Set streaming socket server port [default: %default]", \
|
|
#default=50007)
|
|
#default=PortFinder.old_getport(50000,[]))
|
|
)
|
|
parser.add_option("-e", "--execute", dest="exec_app", action="store", type="string", help="Execute the specified fsw application after socket server and UI are up [default: %default]", \
|
|
default=fsw_app)
|
|
parser.add_option("-L", "--log-file-path", dest="log_file_path", action="store", type="string", help="Path to log files [default: %default]", \
|
|
default=log_file_path)
|
|
parser.add_option("-b", "--logbinary", dest="bin_logger_flag", action="store", type="int", help="Flag to log raw data from socket (1=ON, 0=OFF) [default: %default]", \
|
|
default=Logger.BIN_LOGGER_FLAG)
|
|
parser.add_option("-r", "--log-file-prefix", dest="log_file_prefix", action="store", type="string", help="Prefix in log file path for each run. [default: current date/time]", \
|
|
default=None)
|
|
parser.add_option("-l", "--log-time", dest="log_time", action="store", type="string", help="Time used for logging. (local, GMT)", \
|
|
default="local")
|
|
parser.add_option("-n", "--no-about", dest="no_about", action="store_true", help="Do not show about text screen on start", \
|
|
default=True)
|
|
parser.add_option("-t", "--title", dest="title", action="store",type="string", help="Set GUI title", default="Fprime")
|
|
|
|
parser.add_option("-x", "--packetspec", dest="packetspec", action="store",type="string", help="Path to packet specification file", default=None)
|
|
|
|
|
|
#parser.add_option("-v", "--verbose", dest="verbose", action="count", help="set verbosity level [default: %default]")
|
|
|
|
# process options
|
|
(opts, args) = parser.parse_args(argv)
|
|
#
|
|
# Launch the Threaded TCP Server here...
|
|
|
|
# check for gm time in options
|
|
if not (opts.log_time == "GMT" or opts.log_time == "local"):
|
|
raise Exception("-l,--log-time must be \"local\" or \"GMT\"")
|
|
if opts.log_time == "GMT" and opts.log_file_prefix == None:
|
|
opts.log_file_prefix = time.strftime("%Y-%m-%d_%H-%M-%S",time.gmtime())
|
|
elif opts.log_time == "local" and opts.log_file_prefix == None:
|
|
opts.log_file_prefix = time.strftime("%Y-%m-%d_%H-%M-%S",time.localtime())
|
|
|
|
# Make sure dictionary directory exists
|
|
print "Generated path %s"%opts.generated_path
|
|
if not os.path.exists(opts.generated_path):
|
|
sys.stderr.write("Error: dictionary directory %s does not exist."%opts.generated_path)
|
|
sys.exit(-1)
|
|
|
|
#
|
|
if opts.connect == True or opts.exec_app != None:
|
|
connect(opts)
|
|
opts.connect = True
|
|
|
|
# set the binary logger flag
|
|
Logger.setBinLoggerFlag(opts.bin_logger_flag)
|
|
|
|
# make the
|
|
|
|
#
|
|
# For every console output log to a default file and stdout.
|
|
#
|
|
logfile = 'StdOut.log'
|
|
p = opts.log_file_path + os.sep + opts.log_file_prefix + os.sep + "stdout"
|
|
if not os.path.exists(p):
|
|
os.makedirs(p)
|
|
f = p + os.sep + "stdout.log"
|
|
#
|
|
# display configuration before starting GUI here...
|
|
#
|
|
sep_line = 80*"="
|
|
logger = Logger.connectOutputLogger(f,'stdout')
|
|
logger.info("Created log: %s" % f)
|
|
logger.info("User: %s" % os.environ['USER'])
|
|
(sysname, nodename, release, version, machine) = os.uname()
|
|
logger.info("OS Name: %s" % sysname)
|
|
logger.info("Machine Network Host Name: %s" % nodename)
|
|
logger.info("Release: %s" % release)
|
|
logger.info("Version: %s" % version)
|
|
logger.info("Machine: %s" % machine)
|
|
#
|
|
logger.info(sep_line)
|
|
logger.info("Generated command/telemetry definition files: %s" % opts.generated_path)
|
|
logger.info("Threaded TCP Socket Server Address: %s" % opts.addr)
|
|
logger.info("Connection and starting Threaded TCP Socket Server: %s" % opts.connect)
|
|
logger.info("Threaded TCP Socket Server Port: %s" % opts.port)
|
|
logger.info("Execution of FSW Binary Application: %s" % opts.exec_app)
|
|
logger.info("Path to log files: %s" % opts.log_file_path)
|
|
logger.info(sep_line)
|
|
LOGGER = logger
|
|
#
|
|
# MAIN BODY #
|
|
root = main_window_start(opts)
|
|
root.geometry("900x800+10+10")
|
|
#
|
|
# Launch an FSW applicaiton but only after the gse.py is ready.
|
|
#
|
|
if opts.exec_app != None:
|
|
root.after(1000, execute, opts)
|
|
root.mainloop()
|
|
|
|
except fprime.gse.controllers.exceptions.GseControllerException, e:
|
|
sys.stderr.write("Exception: %s\n"%e.getMsg())
|
|
traceback.print_exc()
|
|
return 2
|
|
|
|
except Exception, e:
|
|
indent = len(program_name) * " "
|
|
sys.stderr.write(program_name + ": " + repr(e) + "\n")
|
|
sys.stderr.write(indent + " for help use --help\n")
|
|
traceback.print_exc()
|
|
return 2
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|