From 2ff4767a8af5465288e7032bf8d14a059ab650bd Mon Sep 17 00:00:00 2001 From: Leor Bleier Date: Thu, 14 May 2020 11:37:11 -0400 Subject: [PATCH] Fix #72 - Upgrade PyQt4 to PyQt5 Further edits based on CCB feedback, and other fixes as necessary --- .gitignore | 2 - GroundSystem.py | 22 ++++--- Guide-GroundSystem.md | 6 +- RoutingService.py | 2 - Subsystems/cmdGui/CHeaderParser.py | 42 ++----------- Subsystems/cmdGui/CommandSystem.py | 2 +- Subsystems/cmdGui/HTMLDocsParser.py | 89 +++++++++++++-------------- Subsystems/cmdGui/Parameter.py | 4 -- Subsystems/cmdGui/UdpCommands.py | 6 +- Subsystems/tlmGUI/EventMessage.py | 4 -- Subsystems/tlmGUI/GenericTelemetry.py | 4 +- Subsystems/tlmGUI/TelemetrySystem.py | 4 -- 12 files changed, 67 insertions(+), 120 deletions(-) diff --git a/.gitignore b/.gitignore index 001c426..9c79f62 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ *.pyc cmdUtil .DS_Store -Subsystems/cmdGui/CHeaderParser.py -Subsystems/cmdGui/CHeaderParser.py \ No newline at end of file diff --git a/GroundSystem.py b/GroundSystem.py index 29fe5cd..3688960 100644 --- a/GroundSystem.py +++ b/GroundSystem.py @@ -38,7 +38,6 @@ # CFS Ground System: Setup and manage the main window # class GroundSystem(QMainWindow, Ui_MainWindow): - # # Init the class # @@ -76,7 +75,6 @@ def getSelectedSpacecraftName(self): # def DisplayErrorMessage(self, message): print(message) - # alert = QMessageBox() self.alert.setText(message) self.alert.setIcon(QMessageBox.Warning) self.alert.exec_() @@ -104,14 +102,18 @@ def startCmdSystem(): ['python3', f'{ROOTDIR}/Subsystems/cmdGui/CommandSystem.py']) # Start FDL-FUL gui system - #def startFDLSystem(self): - # selectedSpacecraft = self.getSelectedSpacecraftName() - # if selectedSpacecraft == 'All': - # subscription = '' - # self.DisplayErrorMessage('Cannot open FDL manager.\nNo spacecraft selected.') - # else: - # subscription = '--sub=GroundSystem.' + selectedSpacecraft - # os.system('( cd Subsystems/fdlGui/ && python FdlSystem.py ' + subscription + ' ) & ') + def startFDLSystem(self): + selectedSpacecraft = self.getSelectedSpacecraftName() + if selectedSpacecraft == 'All': + subscription = '' + self.DisplayErrorMessage( + 'Cannot open FDL manager.\nNo spacecraft selected.') + else: + subscription = f'--sub=GroundSystem.{selectedSpacecraft}' + subprocess.Popen([ + 'python3', f'{ROOTDIR}/Subsystems/fdlGui/FdlSystem.py', + subscription + ]) # Update the combo box list in gui def updateIpList(self, ip, name): diff --git a/Guide-GroundSystem.md b/Guide-GroundSystem.md index f8bae56..a139c80 100644 --- a/Guide-GroundSystem.md +++ b/Guide-GroundSystem.md @@ -23,13 +23,13 @@ Future enhancements: ## Install and run Before launching the Ground System make sure that: -- PyQt4 is installed, +- PyQt5 is installed, - PyZMQ is installed, - cmdUtil is compiled. Installing and running cFS Ground System on Ubuntu: -1. ```sudo apt-get install python3-pyqt4``` +1. ```sudo apt-get install python3-pyqt5``` 1. ```sudo apt-get install python3-zmq``` 1. ```sudo apt-get install libcanberra-gtk-module``` 1. ```cd Subsystems/cmdUtil/ && make``` @@ -46,7 +46,7 @@ This section was made to help developers who are adding core Flight Software (cF 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`. Expected file structure: diff --git a/RoutingService.py b/RoutingService.py index 66b9e7d..47139ca 100644 --- a/RoutingService.py +++ b/RoutingService.py @@ -120,8 +120,6 @@ def forwardMessage(self, datagram, hostName): def getPktId(datagram): # Read the telemetry header streamId = unpack(">H", datagram[:2]) - # Uncomment the next line to debug - # print("Packet ID =", hex(streamId)) return hex(streamId[0]) # Close ZMQ vars diff --git a/Subsystems/cmdGui/CHeaderParser.py b/Subsystems/cmdGui/CHeaderParser.py index fcd48bd..52fd4dc 100644 --- a/Subsystems/cmdGui/CHeaderParser.py +++ b/Subsystems/cmdGui/CHeaderParser.py @@ -103,12 +103,6 @@ def getFileList(filename='CHeaderParser-hdr-paths.txt'): l = l.strip() if l and not l.startswith("#"): paths.append(l) - # Don't worry about comment lines - # if line.find('#') == -1: - # Don't worry about empty lines - # if line != '': - # Add line to list of paths - # paths.append(line) print(f"Using header files found in {filename}") # Send paths back to caller function return paths @@ -149,8 +143,6 @@ def getFileList(filename='CHeaderParser-hdr-paths.txt'): for single_line in single_hdr: master_hdr.append(single_line) - #print "Master Header Length: " + str(len(master_hdr)) - # Reads and saves command and parameter information # Look through each line of the header file for command definitions for single_line in master_hdr: @@ -180,9 +172,6 @@ def getFileList(filename='CHeaderParser-hdr-paths.txt'): # structure single_line = single_line[:single_line.rfind('//')] - #else: - # print "Did not find any comments in definition." - # Split single line into list for indexing definition = single_line.split() @@ -195,30 +184,15 @@ def getFileList(filename='CHeaderParser-hdr-paths.txt'): cmdDesc.append(definition[1]) cmdCodes.append(definition[2]) - #else: - # 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( - "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" - ) + print(("We need to save the command into to a pickle file " + "in 'CommandFile/'.\nPlease 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 # therefore picklefile = CommandFiles/app_msg - #pickle_file = 'CommandFiles/'+file_split[-2] pickle_file = f'{ROOTDIR}/CommandFiles/{cmd_file_name}' # Open pickle file for storing command codes/descriptions @@ -456,14 +430,8 @@ def getFileList(filename='CHeaderParser-hdr-paths.txt'): print("Array size:", array_size) - # Set flag initially to false in order to get into while loop - # array_size_within_limit = False - - # Check conditions before loop to see if loop is even necessary - # array_size_within_limit = array_size.isdigit() and int( - # array_size) in range(129) - - # This while loop will make sure that the user input is both + # This while loop will make sure that + # the user input is both # - a valid integer # - between 0 and 128 (inclusively) while not array_size.isdigit() or int( diff --git a/Subsystems/cmdGui/CommandSystem.py b/Subsystems/cmdGui/CommandSystem.py index 2f3430b..710d780 100644 --- a/Subsystems/cmdGui/CommandSystem.py +++ b/Subsystems/cmdGui/CommandSystem.py @@ -76,7 +76,7 @@ def checkParams(idx): pickle_file = f'{ROOTDIR}/ParameterFiles/{quickParam[idx]}' try: with open(pickle_file, 'rb') as pickle_obj: - _, paramNames, _, _, _, _ = pickle.load(pickle_obj) + paramNames = pickle.load(pickle_obj)[1] return len(paramNames) > 0 except IOError: return False diff --git a/Subsystems/cmdGui/HTMLDocsParser.py b/Subsystems/cmdGui/HTMLDocsParser.py index 455f4ad..f932954 100644 --- a/Subsystems/cmdGui/HTMLDocsParser.py +++ b/Subsystems/cmdGui/HTMLDocsParser.py @@ -17,21 +17,14 @@ # See the License for the specific language governing permissions and # limitations under the License. # -import sys -import csv -import getopt -import subprocess -import shlex -import re + import glob import pickle - +import re from html.parser import HTMLParser -from struct import * class HTMLDocsParser(HTMLParser): - # # Initializes allData variable # @@ -42,15 +35,16 @@ def reset(self): # # Appends HTML file content to allData variable # - def handle_data(self, text): - if text.strip() != '': # excludes new lines - self.allData.append(text.strip()) + def handle_data(self, data): + if data.strip(): # excludes new lines + self.allData.append(data.strip()) # # Determines UNIX data type of parameter # - def findDataTypeNew(self, dataTypeOrig, paramLen): - if paramLen != '': # assumes all string types have length enclosed in brackets + @staticmethod + def findDataTypeNew(dataTypeOrig, paramLn): + if paramLn: # assumes all string types have length enclosed in brackets return '--string' if dataTypeOrig in ('uint8', 'boolean'): return '--byte' @@ -65,25 +59,25 @@ def findDataTypeNew(self, dataTypeOrig, paramLen): # # Determines character array size for string types # - def findStringLen(self, keyword): + @staticmethod + def findStringLen(kywd): hdr_files = glob.glob('../../../build/cpu1/inc/*.h') hdr_files += glob.glob('../../fsw/cfe-core/src/inc/cfe_*.h') hdr_files += glob.glob('../../fsw/mission_inc/cfe_mission_cfg.h') val = '' found = False - i = 0 + k = 0 - while not found and i < len(hdr_files): - with open(hdr_files[i]) as hdr_obj: + while not found and k < len(hdr_files): + with open(hdr_files[k]) as hdr_obj: file_lines = hdr_obj.readlines() - j = 0 - while found == False and j < len(file_lines): - if '#define ' + keyword in file_lines[j]: + l = 0 + while not found and l < len(file_lines): + if f'#define {kywd}' in file_lines[l]: found = True - val = file_lines[j].split()[2] - j += 1 - i += 1 - + val = file_lines[l].split()[2] + l += 1 + k += 1 return val @@ -104,7 +98,7 @@ def findStringLen(self, keyword): with open(html_file) as file_obj: # opens HTML file reader = file_obj.read() # reads HTML file parser.feed(reader) # feeds file contents to parser - data = parser.allData + allData = parser.allData dataTypesOrig = [] # uint8, uint16, uint32, char, boolean paramNames = [] # parameter name @@ -114,32 +108,35 @@ def findStringLen(self, keyword): stringLen = [] # evaluated parameter length try: - i = data.index("Data Fields") + 1 - j = data.index("Detailed Description") - while i < j: # iterates through lines between Data Fields and Detailed Description - + i = allData.index("Data Fields") + 1 + j = allData.index("Detailed Description") + # iterates through lines between Data Fields and Detailed Description + while i < j: # skips header parameters - if 'Header' in data[i + 1] or 'Hdr' in data[i + 1]: + if any([x in allData[i + 1] for x in ('Header', 'Hdr')]): + # if 'Header' in data[i + 1] or 'Hdr' in data[i + 1]: i += 1 - while 'uint' not in data[i] and 'char' not in data[ - i] and i < j: + while not any( + [x in allData[i] + for x in ('uint', 'char')]) and i < j: + # while 'uint' not in data[i] and 'char' not in data[ + # i] and i < j: i += 1 else: - dataTypesOrig.append(data[i]) # stores data type + dataTypesOrig.append(allData[i]) # stores data type i += 1 - paramNames.append(data[i]) # stores parameter name + paramNames.append(allData[i]) # stores parameter name i += 1 param_len = '' - if '[' in data[i]: - param_len = data[ + if '[' in allData[i]: + param_len = allData[ i] # stores string length if provided i += 1 paramLen.append(param_len) desc_string = '' - while 'uint' not in data[i] and 'char' not in data[ - i] and i < j: - desc_string = desc_string + ' ' + data[i] + while not any([x in allData[i] for x in ('uint', 'char')]) and i < j: + desc_string = f'{desc_string} {allData[i]}' i += 1 paramDesc.append(desc_string.lstrip() ) # stores parameter description @@ -152,15 +149,15 @@ def findStringLen(self, keyword): # finds size of character array if type --string keyword = '' if dataTypeNew == '--string': - keyword = re.sub('\[|\]|\(|\)', '', + keyword = re.sub(r'\[|\]|\(|\)', '', paramLen[-1]) # removes brackets - while keyword.isdigit() == False: + while not keyword.isdigit(): keyword = parser.findStringLen(keyword) - keyword = re.sub('\[|\]|\(|\)', '', keyword) + keyword = re.sub(r'\[|\]|\(|\)', '', keyword) if keyword == '0': keyword = input( - paramLen[-1] + - ' not found. Please enter value manually: ') + f'{paramLen[-1]} not found. Please enter value manually: ' + ) stringLen.append(keyword) print("DATA TYPES:", dataTypesOrig) @@ -174,7 +171,7 @@ def findStringLen(self, keyword): print("Data Fields not found in HTML file") # write data to a file - file_split = re.split('/|\.', html_file) + file_split = re.split(r'/|\.', html_file) pickle_file = 'ParameterFiles/' + file_split[-2] with open(pickle_file, 'wb') as pickle_obj: pickle.dump([ diff --git a/Subsystems/cmdGui/Parameter.py b/Subsystems/cmdGui/Parameter.py index 6778075..b069d6b 100644 --- a/Subsystems/cmdGui/Parameter.py +++ b/Subsystems/cmdGui/Parameter.py @@ -34,7 +34,6 @@ class Parameter(QDialog, Ui_Dialog): - # # Initializes Parameter class # @@ -65,12 +64,10 @@ def ProcessSendButton(self): param_list.append(f'{dataType}={input_list[k]}') # --byte=4 k += 1 param_string = ' '.join(param_list) - # print(param_string) launch_string = ( f'{ROOTDIR}/../cmdUtil/cmdUtil --host={pageAddress} ' f'--port={pagePort} --pktid={pagePktId} --endian={pageEndian} ' f'--cmdcode={cmdCode} {param_string.strip()}') - # print launch_string cmd_args = shlex.split(launch_string) subprocess.Popen(cmd_args) self.status_box.setText('Command sent!') @@ -80,7 +77,6 @@ def ProcessSendButton(self): # Main method # if __name__ == '__main__': - # # Initializes variables # diff --git a/Subsystems/cmdGui/UdpCommands.py b/Subsystems/cmdGui/UdpCommands.py index f520aa9..b5a96ed 100644 --- a/Subsystems/cmdGui/UdpCommands.py +++ b/Subsystems/cmdGui/UdpCommands.py @@ -47,9 +47,6 @@ class SubsystemCommands(QDialog, Ui_GenericCommandDialog): - - # pktCount = 0 - # # Init the class # @@ -71,7 +68,7 @@ def checkParams(idx): pf = f'{ROOTDIR}/ParameterFiles/{param_files[idx]}' try: with open(pf, 'rb') as po: - _, paramNames, _, _, _, _ = pickle.load(po) + paramNames = pickle.load(po)[1] return len(paramNames) > 0 # if has parameters except IOError: return False @@ -120,7 +117,6 @@ def usage(): # Main # if __name__ == '__main__': - # # Set defaults for the arguments # diff --git a/Subsystems/tlmGUI/EventMessage.py b/Subsystems/tlmGUI/EventMessage.py index 9d05702..c067f75 100644 --- a/Subsystems/tlmGUI/EventMessage.py +++ b/Subsystems/tlmGUI/EventMessage.py @@ -205,10 +205,6 @@ def usage(): if not subscription or len(subscription.split('.')) < 3: subscription = "GroundSystem" - # arr = subscription.split('.') - # if len(arr) < 3: - # subscription = 'GroundSystem' - print('Event Messages Page started. Subscribed to', subscription) py_endian = '<' if endian == 'L' else '>' diff --git a/Subsystems/tlmGUI/GenericTelemetry.py b/Subsystems/tlmGUI/GenericTelemetry.py index 3510daf..7d7252b 100644 --- a/Subsystems/tlmGUI/GenericTelemetry.py +++ b/Subsystems/tlmGUI/GenericTelemetry.py @@ -36,7 +36,6 @@ class SubsystemTelemetry(QDialog, Ui_GenericTelemetryDialog): - # # Init the class # @@ -77,7 +76,8 @@ def initGTTlmReceiver(self, subscr): self.thread.start() # - # This method processes packets. Called when the TelemetryReceiver receives a message/packet + # This method processes packets. + # Called when the TelemetryReceiver receives a message/packet # def processPendingDatagrams(self, datagram): # diff --git a/Subsystems/tlmGUI/TelemetrySystem.py b/Subsystems/tlmGUI/TelemetrySystem.py index 4c9ce23..1e02aa4 100644 --- a/Subsystems/tlmGUI/TelemetrySystem.py +++ b/Subsystems/tlmGUI/TelemetrySystem.py @@ -22,7 +22,6 @@ import csv import getopt import shlex -# import socket import subprocess import sys from pathlib import Path @@ -38,7 +37,6 @@ class TelemetrySystem(QDialog, Ui_TelemetrySystemDialog): - # # Init the class # @@ -70,8 +68,6 @@ def strToHex(aString): # Dump the telemetry packet # def dumpPacket(self, packetData): - # appIdString = f"{ord(packetData[0]):02X}" - # appIdString += f"{ord(packetData[1]):02X}" appId = (ord(packetData[0]) << 8) + (ord(packetData[1])) print("\n-----------------------------------------------") print("\nPacket: App ID =", hex(appId))