diff --git a/Guide-GroundSystem.txt b/Guide-GroundSystem.txt index fb5e2dd..e751aea 100644 --- a/Guide-GroundSystem.txt +++ b/Guide-GroundSystem.txt @@ -1,4 +1,4 @@ -cFS Ground System Version 2.1.4 +cFS Ground System Version 2.1.5 cFS Ground System Info: @@ -6,7 +6,7 @@ The GroundSystem directory contains the new Ground System project for the cFS, t This ground system supports commanding and receiving telemetry from multiple spacecrafts using UDP. -The Ground System contains a main window that lets you launch the different utilities. To start receiving data from the cFS, you need to enable telemetry first. To enable telemetry, click the "Start Command System" button from the main window, then from the Command System Main Page click the "Enable Tlm" button (you will need to enter the target/destination IP address as an input to this command). +The Ground System contains a main window that lets you launch the different utilities. To start receiving data from the cFS, you need to enable telemetry first. To enable telemetry, click the "Start Command System" button from the main window, then from the Command System Main Page click the "Enable Tlm" button (you will need to enter the target/destination IP address as an input to this command). Note: The Main Window needs to be opened at all times so that the telemetry messages can be forwarded to the Telemetry System. @@ -19,70 +19,28 @@ Future enhancements: Before launching the Ground System make sure that: -> PyQt4 is installed. - -> PyZMQ is installed. + -> PyZMQ is installed. -> cmdUtil is compiled. -Installing and running cFS Ground System on Mac: -Install using Homebrew on Mac (http://brew.sh/) - $ brew install pyqt - $ brew install zeromq - $ ( cd Subsystems/cmdUtil/ && make ) - $ python GroundSystem.py - Installing and running cFS Ground System on Ubuntu: - $ sudo apt-get install python-qt4 python-qt4-dev - $ sudo apt-get install python-zmq + $ sudo apt-get install python3-pyqt4 + $ sudo apt-get install python3-zmq + $ sudo apt-get install libcanberra-gtk-module $ ( cd Subsystems/cmdUtil/ && make ) - $ python GroundSystem.py + $ python3 GroundSystem.py -Installing and running cFS Ground System on CentOS 6: - $ su - $ - $ yum -y update - - #### Install pip and python-development #### - # If you are on a 64-bit CentOS / RHEL based system: - $ wget http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm - $ rpm -ivh epel-release-6-8.noarch.rpm - - # If you are on a 32-bit CentOS / RHEL based system: - $ wget http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm - $ rpm -ivh epel-release-6-8.noarch.rpm - - $ yum install -y python-pip - $ yum install -y python-devel - - #### Install zeroMQ and pyZMQ messaging system #### - $ yum install -y uuid-devel - $ yum install -y pkgconfig - $ yum install -y libtool - $ yum install -y gcc-c++ - $ wget http://download.zeromq.org/zeromq-4.0.5.tar.gz - $ tar xzvf zeromq-4.0.5.tar.gz - $ cd zeromq-4.0.5 - $ ./configure - $ make - $ make install - $ echo /usr/local/lib > /etc/ld.so.conf.d/local.conf - $ ldconfig - $ pip install pyzmq - - #### Install pyQT4 #### - $ yum install -y PyQt4 - $ yum install -y qt qt-demos qt-designer qt4 qt4-designer - - - ### Running Ground System ### - $ python GroundSystem.py +The historically included instructions for running on Mac or CentOS are inluded at the bottom of this document for referance. +Please note that instructions have not been maintained. +Welcoming instruction contributions if any of these are your platform of choice. ############################################################################## ADDING NEW FLIGHT SOFTWARE APPLICATION TO GROUND SYSTEM COMMAND GUI -This section was made to help developers who are adding core Flight Software (cFS) Applications to the Python-based Ground System that comes with this cFS distribution. +This section was made to help developers who are adding core Flight Software (cFS) Applications to the Python-based Ground System that comes with this cFS distribution. The CHeaderParser.py program that should be found in: GroundSystem/Subsystems/cmdGui is an interactive, command line based program to help walk developers through the process of adding custom cFS applications to the Ground System. Along with CHeaderParser.py is a configuration file that CHeaderParser uses to find the proper header files for your "new" cFS application. This file is named 'CHeaderParser-hdr-paths.txt', and should be placed in the same directory as CHeaderParser.py. @@ -97,14 +55,14 @@ cFE-6.4.x-OSS-release/cfe/tools/cFS-GroundSystem/Subsystems/cmdGui/command-pages Steps to adding application commands to the Ground System: 1) Edit 'CHeaderParser-hdr-paths.txt' - 1.1) Locate any header files that contain command code definitions or command structure definitions. + 1.1) Locate any header files that contain command code definitions or command structure definitions. These files typically end in '*app_msg.h' or '*app_msgdefs.h' but could be named anything. - 1.2) Add each one of the paths to a new line in CHeaderParser-hdr-paths.txt + 1.2) Add each one of the paths to a new line in CHeaderParser-hdr-paths.txt 1.3) Comment out any paths/lines that aren't needed with '#' (at the beginning of the line) 2) Run CHeaderParser 2.1) Call CHeaderParser using python - ~$ python CHeaderParser.py + ~$ python3 CHeaderParser.py 2.2) The program will prompt you to enter a filename for the application. This will create a pickle file for your application named CommandFiles/. Notice that this file will be stored in the CommandFiles directory. This same filename will be used in command-pages.txt later. 2.3) Type 'yes' if any commands in your application have parameters @@ -123,7 +81,7 @@ Steps to adding application commands to the Ground System: 3.6) Column 6 - Command Send Address (default 127.0.0.1) 3.7) Column 7 - Command Send Port (default 1234) - Notes: + Notes: - USE ONLY SPACES, NO TABS (Remember, it's Python.) - Don't leave any empty lines in command-pages.txt, this could cause errors when running GroundSystem.py and CommandSystem.py @@ -145,9 +103,9 @@ Issue: Cannot Send Command, receiving the following error: > Traceback (most recent call last): > File "Parameter.py", line 100, in ProcessSendButton > subprocess.Popen(cmd_args, stdout=subprocess.PIPE) -> File "/usr/lib/python2.6/subprocess.py", line 642, in __init__ +> File "/usr/lib/python3.7/subprocess.py", line 642, in __init__ > errread, errwrite) -> File "/usr/lib/python2.6/subprocess.py", line 1234, in _execute_child +> File "/usr/lib/python3.7/subprocess.py", line 1234, in _execute_child > raise child_exception > OSError: [Errno 8] Exec format error @@ -157,12 +115,55 @@ To fix this problem, use the Makefile inside of the cmdUtil directory to compile $ cd Subsystems/cmdUtil $ make $ cd ../.. -$ python GroundSystem.py +$ python3 GroundSystem.py ----------------------------------------------------------------------------- +Historically included instructions for running on Mac or CentOS: + +Installing and running cFS Ground System on Mac: +Install using Homebrew on Mac (http://brew.sh/) + $ brew install pyqt + $ brew install zeromq + $ ( cd Subsystems/cmdUtil/ && make ) + $ python GroundSystem.py +Installing and running cFS Ground System on CentOS 6: + $ su + $ + $ yum -y update + #### Install pip and python-development #### + # If you are on a 64-bit CentOS / RHEL based system: + $ wget http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm + $ rpm -ivh epel-release-6-8.noarch.rpm + # If you are on a 32-bit CentOS / RHEL based system: + $ wget http://download.fedoraproject.org/pub/epel/6/i386/epel-release-6-8.noarch.rpm + $ rpm -ivh epel-release-6-8.noarch.rpm + $ yum install -y python-pip + $ yum install -y python-devel + #### Install zeroMQ and pyZMQ messaging system #### + $ yum install -y uuid-devel + $ yum install -y pkgconfig + $ yum install -y libtool + $ yum install -y gcc-c++ + $ wget http://download.zeromq.org/zeromq-4.0.5.tar.gz + $ tar xzvf zeromq-4.0.5.tar.gz + $ cd zeromq-4.0.5 + $ ./configure + $ make + $ make install + $ echo /usr/local/lib > /etc/ld.so.conf.d/local.conf + $ ldconfig + $ pip install pyzmq + + #### Install pyQT4 #### + $ yum install -y PyQt4 + $ yum install -y qt qt-demos qt-designer qt4 qt4-designer + + + ### Running Ground System ### + $ python GroundSystem.py diff --git a/README.md b/README.md index f23caad..fb64e9d 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,9 @@ See Guide-GroundSystem.txt for more information. ## Version Notes +- 2.1.5: DEVELOPMENT + - Updated build instructions for Python 3 + - See https://github.com/nasa/cFS-GroundSystem/pull/64 - 2.1.4: DEVELOPMENT - Finish conversion to python 3 - cmdutil now accepts --word as alias to --long @@ -15,7 +18,7 @@ See Guide-GroundSystem.txt for more information. - 2.1.3: DEVELOPMENT - Minor updates to work with python 3 - No longer compatible with python 2.7 - - Note issue #50 is to update the related documentation + - Note issue #50 is to update the related documentation - See https://github.com/nasa/cFS-GroundSystem/pull/47 - 2.1.2: DEVELOPMENT - Minor updates (see https://github.com/nasa/cFS-GroundSystem/pull/39) @@ -36,4 +39,3 @@ As a lab application, extensive testing is not performed prior to release and on For best results, submit issues:questions or issues:help wanted requests at https://github.com/nasa/cFS. Official cFS page: http://cfs.gsfc.nasa.gov - diff --git a/Subsystems/cmdGui/CHeaderParser-hdr-paths.txt b/Subsystems/cmdGui/CHeaderParser-hdr-paths.txt index 85e7e4c..a6a7d8c 100644 --- a/Subsystems/cmdGui/CHeaderParser-hdr-paths.txt +++ b/Subsystems/cmdGui/CHeaderParser-hdr-paths.txt @@ -13,5 +13,5 @@ # This program does support relative paths but if the program cannot # find your header files, try using absolute paths. # -#../../../../../apps/to_lab/fsw/src/to_lab_msg.h -#../../../../../apps/ci_lab/fsw/src/ci_lab_msg.h +#../../../../apps/to_lab/fsw/src/to_lab_msg.h +#../../../../apps/ci_lab/fsw/src/ci_lab_msg.h diff --git a/Subsystems/cmdGui/CHeaderParser.py b/Subsystems/cmdGui/CHeaderParser.py index 1d8d85d..f55f78a 100644 --- a/Subsystems/cmdGui/CHeaderParser.py +++ b/Subsystems/cmdGui/CHeaderParser.py @@ -98,7 +98,7 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): # Try to open textfile list of header files try: - textfile = open(filename, 'rb') + textfile = open(filename, 'r') for line in textfile: # Remove whitespace before and after line = line.strip() @@ -108,16 +108,16 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): if line != '': # Add line to list of paths paths.append(line) - print "Using header files found in " + filename + print ("Using header files found in " + filename) # Send paths back to caller function return paths except IOError as e: - print "Couldn't find default file. Checking command line arguments." + print ("Couldn't find default file. Checking command line arguments.") except: - print "Unexpected error:", sys.exc_info()[0] + print ("Unexpected error:", sys.exc_info()[0]) - print "No header files found. Please make sure to provide the " - print "default file for loading headers (CHeaderParser-hdr-paths.txt) " + print ("No header files found. Please make sure to provide the ") + print ("default file for loading headers (CHeaderParser-hdr-paths.txt) ") # If we got to here, we couldn't find any header files, return empty list return [] @@ -135,7 +135,7 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): # If list is empty, exit now if not file_list: - print "ERROR: Empty file list. Nothing to be done. Exiting now." + print ("ERROR: Empty file list. Nothing to be done. Exiting now.") exit() # initialize command codes/descriptions lists as empty lists @@ -148,7 +148,7 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): # Concatonate all headers into one variable for referencing for hdr_file in file_list: # open header file as single header - single_hdr = open(hdr_file, 'rb') + single_hdr = open(hdr_file, 'r') # dump single header into master for single_line in single_hdr: master_hdr.append(single_line) @@ -203,16 +203,16 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): # print "length not 3, see line below" # print definition - #print "List of Command Descriptions Below:" - #print cmdDesc - #print "--------------------------------------------------------------" - #print "List of Command Codes Below:" - #print cmdCodes - #print "--------------------------------------------------------------" + #print ("List of Command Descriptions Below:") + #print (cmdDesc) + #print ("--------------------------------------------------------------") + #print ("List of Command Codes Below:") + #print (cmdCodes) + #print ("--------------------------------------------------------------") - print "We need to save the command into to a pickle file in 'CommandFile/'. " - print "Please do not use any spaces/quotes in your filename. Ex: my_app_cmd_file" - cmd_file_name = raw_input("What would you like the command file to be saved as? ") + print ("We need to save the command into to a pickle file in 'CommandFile/'. ") + print ("Please do not use any spaces/quotes in your filename. Ex: my_app_cmd_file") + cmd_file_name = input("What would you like the command file to be saved as? ") # starting from last index (-1) going backward # (from example above) file_split[-2] = app_msg @@ -220,6 +220,7 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): #pickle_file = 'CommandFiles/'+file_split[-2] pickle_file = 'CommandFiles/' + cmd_file_name + # Open pickle file for storing command codes/descriptions with open(pickle_file, 'wb') as pickle_obj: # @@ -240,50 +241,50 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): cmd_index = 0 # Print a list of unused commands for the user to pick from. - print "" - print "Unused Commands" - print "-----------------------------------------" + print ("") + print ("Unused Commands") + print ("-----------------------------------------") for cmd_index in range(0, len(unused_cmdDesc)): - print "Command (" + str(cmd_index) + " of " + str(len(unused_cmdDesc)-1) + ") " + unused_cmdDesc[cmd_index] + print ("Command (" + str(cmd_index) + " of " + str(len(unused_cmdDesc)-1) + ") " + unused_cmdDesc[cmd_index]) # Get user input to see if any commands from this file require parameters - more_param_cmds = raw_input('Do any commands in ' + cmd_file_name + ' require parameters? (yes/no): ') + more_param_cmds = input('Do any commands in ' + cmd_file_name + ' require parameters? (yes/no): ') - while string.lower(more_param_cmds) not in ['yes', 'y', 'no', 'n']: - print "Your response was not valid. Please enter (yes, y, no, or n)." - more_param_cmds = raw_input('Do any commands in ' + cmd_file_name + ' require parameters? (yes/no): ') + while str.lower(more_param_cmds) not in ['yes', 'y', 'no', 'n']: + print ("Your response was not valid. Please enter (yes, y, no, or n).") + more_param_cmds = input('Do any commands in ' + cmd_file_name + ' require parameters? (yes/no): ') # Check for exit condition - if string.lower(more_param_cmds) == 'no' or \ - string.lower(more_param_cmds) == 'n': - print "You have chosen to exit. Exiting now." + if str.lower(more_param_cmds) == 'no' or \ + str.lower(more_param_cmds) == 'n': + print ("You have chosen to exit. Exiting now.") exit() # Continue onto creating parameter files if yes - elif string.lower(more_param_cmds) == 'yes' or \ - string.lower(more_param_cmds) == 'y': + elif str.lower(more_param_cmds) == 'yes' or \ + str.lower(more_param_cmds) == 'y': # Continue to ask user for commands with parameters until we get -1 to exit. while True: # Get user input - command_choice = int(raw_input("Which command would you like to add parameters to (-1 to exit)? ")) + command_choice = int(input("Which command would you like to add parameters to (-1 to exit)? ")) # Check for exit condition if command_choice == -1: - print "You have chosen to exit early. Exiting now." + print ("You have chosen to exit early. Exiting now.") break # Make sure the choice is within range while command_choice not in range(0, len(unused_cmdDesc)): - print "You entered " + str(command_choice) + ", but that isn't an option." - print "Choose from the list above or choose -1 to exit." + print ("You entered " + str(command_choice) + ", but that isn't an option.") + print ("Choose from the list above or choose -1 to exit.") # Get user input - command_choice = int(raw_input("Which command would you like to add parameters to? ")) + command_choice = int(input("Which command would you like to add parameters to? ")) # Check for exit condition if command_choice == -1: - print "You have chosen to exit early. Exiting now." + print ("You have chosen to exit early. Exiting now.") exit() cmdName = unused_cmdDesc[command_choice] @@ -301,7 +302,7 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): # structure can be found list_cmd_structs = [] - print "This program will now attempt to find the command structure for " + cmdName + print ("This program will now attempt to find the command structure for " + cmdName) # create a copy of file_lines for parsing structures file_lines = list(master_hdr) @@ -350,36 +351,36 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): # After exiting this while loop, cmdStruct should contain a list of lists # The nested lists should contain line numbers to each structure in file for line_list in list_cmd_structs: - print "" - print "Showing structure " + str(list_cmd_structs.index(line_list)) + " of " + str(len(list_cmd_structs)-1) + " below." - print "--------------------------------------------" + print ("") + print ("Showing structure " + str(list_cmd_structs.index(line_list)) + " of " + str(len(list_cmd_structs)-1) + " below.") + print ("--------------------------------------------") for line_num in line_list: # Print the line from the file using the index from the list - print file_lines[line_num].strip() - print "--------------------------------------------" + print (file_lines[line_num].strip()) + print ("--------------------------------------------") # Give the user the option to exit too. - print "Choose from the list above or choose -1 to exit." + print ("Choose from the list above or choose -1 to exit.") # Get choice of structure from user. - struct_choice = int(raw_input("Which of the above structures would you like to use? ")) + struct_choice = int(input("Which of the above structures would you like to use? ")) # Check for exit condition if struct_choice == -1: - print "You have chosen to exit early. Exiting now." + print ("You have chosen to exit early. Exiting now.") exit() # Make sure the choice is valid while struct_choice not in range(0, len(list_cmd_structs)): - print "You entered " + str(struct_choice) + ", but that isn't an option." - print "Choose from the list above or choose -1 to exit." + print ("You entered " + str(struct_choice) + ", but that isn't an option.") + print ("Choose from the list above or choose -1 to exit.") # Get user input - struct_choice = int(raw_input("Which of the above structures would you like to use? ")) + struct_choice = int(input("Which of the above structures would you like to use? ")) # Check for exit condition if struct_choice == -1: - print "You have chosen to exit early. Exiting now." + print ("You have chosen to exit early. Exiting now.") exit() # After exiting the while loop, user's structure choice should be a valid assignment @@ -395,21 +396,21 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): while param_line in range(0, len(cmd_struct_lines)): # Display the command structure with indexed before each line - print "\n\n" + print ("\n\n") for line_num in range(0, len(cmd_struct_lines)): # Dereference the index number in cmd_struct_lines to get the actual line number actual_line = cmd_struct_lines[line_num] # print the line of the file with our "line number" next to it - print "Line (" + str(line_num) + ") -> " + file_lines[actual_line].strip() + print ("Line (" + str(line_num) + ") -> " + file_lines[actual_line].strip()) # Prompt the user for line number - param_line = int(raw_input("Enter the line of the parameter from the above print-out (-1 to stop): ")) + param_line = int(input("Enter the line of the parameter from the above print-out (-1 to stop): ")) # Check exit condition if param_line == -1: - print "You have chosen to stop adding parameters." + print ("You have chosen to stop adding parameters.") break # Dereference the index number in cmd_struct_lines to get the actual line number @@ -435,7 +436,7 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): # If no type could match, ask user for data type if dataTypeNew == '': typeNew = parser.findKeyword(dataTypesOrig[-1]) - dataTypeNew = raw_input('Data type for '+paramNames[-1]+' not found. Please enter new data type by hand: ') + dataTypeNew = input('Data type for '+paramNames[-1]+' not found. Please enter new data type by hand: ') dataTypesNew.append(dataTypeNew) @@ -457,7 +458,7 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): # Add array size to the parameter list paramLens.append(array_size) - print "Array size: " + str(array_size) + print ("Array size: " + str(array_size)) # Set flag initially to false in order to get into while loop array_size_within_limit = False @@ -475,20 +476,20 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): while (not str(array_size).isdigit()) or (not array_size_within_limit): # User input is not an integer if not str(array_size).isdigit(): - print "Could not translate " + str(array_name_size[1]) + "." + print ("Could not translate " + str(array_name_size[1]) + ".") try: # Try to translate user input to an integer - array_size = int(raw_input("Please enter the defined value for " + str(array_name_size[1]) + " (0 - 128): ")) + array_size = int(input("Please enter the defined value for " + str(array_name_size[1]) + " (0 - 128): ")) # If we got an integer, we continue to testing if integer is within range if (array_size < 0) or (128 < array_size): - print "Array size out of bounds. It must be between 0 and 128." + print ("Array size out of bounds. It must be between 0 and 128.") array_size_within_limit = False # Restart the loop, array_size not within limit else: array_size_within_limit = True # End of the loop. except: - print "Could not translate " + str(array_name_size[1]) + " into integer. " + print ("Could not translate " + str(array_name_size[1]) + " into integer. ") # Restart the loop, array_size not integer # Add string length argument to parameter list @@ -499,13 +500,13 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): paramLens.append('') # print the last element of list to see if it worked - print "dataTypeOrig:", dataTypesOrig[-1] - print "dataTypeNew:", dataTypesNew[-1] - print "paramName:", paramNames[-1] - print "paramLen:", paramLens[-1] - print "stringLen:", stringLens[-1] + print ("dataTypeOrig:", dataTypesOrig[-1]) + print ("dataTypeNew:", dataTypesNew[-1]) + print ("paramName:", paramNames[-1]) + print ("paramLen:", paramLens[-1]) + print ("stringLen:", stringLens[-1]) - print "Added: " + paramNames[-1] + " with type " + dataTypesNew[-1] + print ("Added: " + paramNames[-1] + " with type " + dataTypesNew[-1]) # Remove used parameter from command structure lines # so that the user doesn't choose the same parameter twice @@ -538,15 +539,15 @@ def getFileList(self, filename='CHeaderParser-hdr-paths.txt'): cmd_index = 0 # Print a list of unused commands for the user to pick from. - print "" - print "Unused Commands" - print "-----------------------------------------" + print ("") + print ("Unused Commands") + print ("-----------------------------------------") for cmd_index in range(0, len(unused_cmdDesc)): - print "Command (" + str(cmd_index) + " of " + str(len(unused_cmdDesc)-1) + ") " + unused_cmdDesc[cmd_index] + print ("Command (" + str(cmd_index) + " of " + str(len(unused_cmdDesc)-1) + ") " + unused_cmdDesc[cmd_index]) # End of 'while True:' # We must have received a -1 when prompting user for the next command. - print "Thank you for using CHeaderParser." - print "The following commands have been added with parameters: " - print used_cmdDesc + print ("Thank you for using CHeaderParser.") + print ("The following commands have been added with parameters: ") + print (used_cmdDesc)