From a0d1872199b6bea81678ec171ef52dda139d063c Mon Sep 17 00:00:00 2001 From: Leor Bleier Date: Tue, 23 Jun 2020 15:39:25 -0400 Subject: [PATCH] WIP: Enhancement #103 - Implemented native cmdUtil Native cmdUtil has only subset of full cmdUtil functionality Also implemented updates to GUI and backend to support custom byte offsets in tlm and cmd --- GroundSystem.py | 41 +++++++++++---- MainWindow.ui | 75 ++++++++++++++++++++++++--- Subsystems/cmdGui/MiniCmdUtil.py | 69 ++++++++++++++++++++++++ Subsystems/tlmGUI/GenericTelemetry.py | 2 +- Ui_MainWindow.py | 71 +++++++++++++++++-------- common/shareddata.py | 4 +- 6 files changed, 221 insertions(+), 41 deletions(-) create mode 100644 Subsystems/cmdGui/MiniCmdUtil.py diff --git a/GroundSystem.py b/GroundSystem.py index 732effa..3a92fdb 100644 --- a/GroundSystem.py +++ b/GroundSystem.py @@ -39,6 +39,9 @@ # CFS Ground System: Setup and manage the main window # class GroundSystem(QMainWindow, Ui_MainWindow): + HDR_VER_1_OFFSET = 0 + HDR_VER_2_OFFSET = 4 + # # Init the class # @@ -51,8 +54,10 @@ def __init__(self): self.pushButtonStartTlm.clicked.connect(self.startTlmSystem) self.pushButtonStartCmd.clicked.connect(self.startCmdSystem) - self.cbHeaderVer.currentIndexChanged.connect(self.setFixedOffset) - self.sbOffset.valueChanged.connect(self.getOffset) + self.cbTlmHeaderVer.currentIndexChanged.connect(self.setTlmOffset) + self.cbCmdHeaderVer.currentIndexChanged.connect(self.setCmdOffsets) + for sb in (self.sbTlmOffset, self.sbCmdOffsetPri, self.sbCmdOffsetSec): + sb.valueChanged.connect(self.saveOffsets) # Init lists self.ipAddressesList = ['All'] self.spacecraftNames = ['All'] @@ -115,19 +120,35 @@ def startFDLSystem(self): subscription ]) - def setFixedOffset(self): - selectedVer = self.cbHeaderVer.currentText().strip() + def setTlmOffset(self): + selectedVer = self.cbTlmHeaderVer.currentText().strip() + if selectedVer == "Custom": + self.sbTlmOffset.setEnabled(True) + else: + self.sbTlmOffset.setEnabled(False) + if selectedVer == "1": + self.sbTlmOffset.setValue(self.HDR_VER_1_OFFSET) + elif selectedVer == "2": + self.sbTlmOffset.setValue(self.HDR_VER_2_OFFSET) + + def setCmdOffsets(self): + selectedVer = self.cbCmdHeaderVer.currentText().strip() if selectedVer == "Custom": - self.sbOffset.setEnabled(True) + self.sbCmdOffsetPri.setEnabled(True) + self.sbCmdOffsetSec.setEnabled(True) else: - self.sbOffset.setEnabled(False) + self.sbCmdOffsetPri.setEnabled(False) + self.sbCmdOffsetSec.setEnabled(False) if selectedVer == "1": - self.sbOffset.setValue(0) + self.sbCmdOffsetPri.setValue(self.HDR_VER_1_OFFSET) elif selectedVer == "2": - self.sbOffset.setValue(4) + self.sbCmdOffsetPri.setValue(self.HDR_VER_2_OFFSET) + self.sbCmdOffsetSec.setValue(self.HDR_VER_1_OFFSET) - def getOffset(self): - shared.offsetVal = self.sbOffset.value() + def saveOffsets(self): + shared.tlmOffset = self.sbTlmOffset.value() + shared.cmdOffsetPri = self.sbCmdOffsetPri.value() + shared.cmdOffsetSec = self.sbCmdOffsetSec.value() # Update the combo box list in gui def updateIpList(self, ip, name): diff --git a/MainWindow.ui b/MainWindow.ui index 3bcb4e7..3a8cdfe 100644 --- a/MainWindow.ui +++ b/MainWindow.ui @@ -9,8 +9,8 @@ 0 0 - 452 - 265 + 552 + 305 @@ -103,12 +103,12 @@ - 141 + 169 0 - Header version + Tlm header version Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter @@ -116,7 +116,7 @@ - + 132 @@ -146,13 +146,65 @@ + + + + Cmd header version + + + - + + + false + + + <html><head/><body><p>Offset (in bytes) to be <span style=" font-weight:600;">added to</span> existing offsets listed in telemetry text files</p></body></html> + + + QAbstractSpinBox::NoButtons + + + + + + + false + + + <html><head/><body><p>Offset (in bytes) to be added <span style=" font-weight:600;">after</span> the <span style=" font-weight:600;">primary</span> header in a command packet</p></body></html> + + + QAbstractSpinBox::NoButtons + + + + + + + + 1 + + + + + 2 + + + + + Custom + + + + + + false - <html><head/><body><p>Offset (in bytes) to be *added to* existing offsets listed in tlm/cmd text files</p></body></html> + <html><head/><body><p>Offset (in bytes) to be added <span style=" font-weight:600;">after</span> the <span style=" font-weight:600;">secondary</span> header in a command packet</p></body></html> QAbstractSpinBox::NoButtons @@ -162,7 +214,14 @@ - Offset (bytes) + Offsets + + + + + + + (Hover for info) diff --git a/Subsystems/cmdGui/MiniCmdUtil.py b/Subsystems/cmdGui/MiniCmdUtil.py new file mode 100644 index 0000000..398335c --- /dev/null +++ b/Subsystems/cmdGui/MiniCmdUtil.py @@ -0,0 +1,69 @@ +# +# GSC-18128-1, "Core Flight Executive Version 6.7" +# +# Copyright (c) 2006-2019 United States Government as represented by +# the Administrator of the National Aeronautics and Space Administration. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +## This file is a Python implementation of a subset of functions in cmdUtil +## to support the GroundSystem GUI + +import socket +import sys +from pathlib import Path + +ROOTDIR = Path().resolve().parent +sys.path.append(ROOTDIR.parent.parent) +## The two preceding lines must be above +## the next import or the import will fail +import common.shareddata as shared + + +class MiniCmdUtil: + ccsdsExt = bytearray(4) + cfsCmdSecHdr = bytearray(2) + + def __init__(self, + host="127.0.0.1", + port="1234", + endian="BE", + hdrVer=1, + pktID=None, + cmdCode=None, + payload=None): + endians = {"BE": ">", "LE": "<"} + + self.host = host + self.port = port + self.endian = ">" if endian == "BE" else "<" + self.pktID = pktID + self.cmdCode = cmdCode + self.hdrVer = hdrVer + self.payload = payload + + self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + + +def assemblePriHeader(self): + ccsdsPri = bytearray(6) + ccsdsPri[0:2] = self.pktID.to_bytes(2, byteorder='big') + ccsdsPri[2:4] = (0xC000).to_bytes(2, byteorder='big') + totalPacketLen = len(ccsdsPri) + len(self.cfsCmdSecHdr) + if self.hdrVer == 2: + totalPacketLen += len(self.ccsdsExt) + +def assemblePayload(self): + pass \ No newline at end of file diff --git a/Subsystems/tlmGUI/GenericTelemetry.py b/Subsystems/tlmGUI/GenericTelemetry.py index 6ae7a8f..e94cb63 100644 --- a/Subsystems/tlmGUI/GenericTelemetry.py +++ b/Subsystems/tlmGUI/GenericTelemetry.py @@ -60,7 +60,7 @@ def displayTelemetryItem(datagram, tlmIndex, labelField, valueField): TlmField1 = tlmItemFormat[tlmIndex] if TlmField1[0] == "<": TlmField1 = TlmField1[1:] - itemStart = int(tlmItemStart[tlmIndex]) + shared.offsetVal + itemStart = int(tlmItemStart[tlmIndex]) + shared.tlmOffset TlmField2 = datagram[itemStart:itemStart + int(tlmItemSize[tlmIndex])] TlmField = unpack(TlmField1, TlmField2) diff --git a/Ui_MainWindow.py b/Ui_MainWindow.py index ed74554..d020d3f 100644 --- a/Ui_MainWindow.py +++ b/Ui_MainWindow.py @@ -12,7 +12,7 @@ class Ui_MainWindow(object): def setupUi(self, MainWindow): MainWindow.setObjectName("MainWindow") MainWindow.setEnabled(True) - MainWindow.resize(452, 265) + MainWindow.resize(552, 305) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred) sizePolicy.setHorizontalStretch(24) sizePolicy.setVerticalStretch(0) @@ -60,26 +60,48 @@ def setupUi(self, MainWindow): sizePolicy.setVerticalStretch(0) sizePolicy.setHeightForWidth(self.label_4.sizePolicy().hasHeightForWidth()) self.label_4.setSizePolicy(sizePolicy) - self.label_4.setMinimumSize(QtCore.QSize(141, 0)) + self.label_4.setMinimumSize(QtCore.QSize(169, 0)) self.label_4.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter) self.label_4.setObjectName("label_4") self.gridLayout.addWidget(self.label_4, 1, 0, 1, 1) - self.cbHeaderVer = QtWidgets.QComboBox(self.centralwidget) - self.cbHeaderVer.setMinimumSize(QtCore.QSize(132, 0)) - self.cbHeaderVer.setMaximumSize(QtCore.QSize(132, 16777215)) - self.cbHeaderVer.setObjectName("cbHeaderVer") - self.cbHeaderVer.addItem("") - self.cbHeaderVer.addItem("") - self.cbHeaderVer.addItem("") - self.gridLayout.addWidget(self.cbHeaderVer, 1, 1, 1, 1) - self.sbOffset = QtWidgets.QSpinBox(self.centralwidget) - self.sbOffset.setEnabled(False) - self.sbOffset.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) - self.sbOffset.setObjectName("sbOffset") - self.gridLayout.addWidget(self.sbOffset, 1, 2, 1, 1) + self.cbTlmHeaderVer = QtWidgets.QComboBox(self.centralwidget) + self.cbTlmHeaderVer.setMinimumSize(QtCore.QSize(132, 0)) + self.cbTlmHeaderVer.setMaximumSize(QtCore.QSize(132, 16777215)) + self.cbTlmHeaderVer.setObjectName("cbTlmHeaderVer") + self.cbTlmHeaderVer.addItem("") + self.cbTlmHeaderVer.addItem("") + self.cbTlmHeaderVer.addItem("") + self.gridLayout.addWidget(self.cbTlmHeaderVer, 1, 1, 1, 1) + self.label_2 = QtWidgets.QLabel(self.centralwidget) + self.label_2.setObjectName("label_2") + self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1) + self.sbTlmOffset = QtWidgets.QSpinBox(self.centralwidget) + self.sbTlmOffset.setEnabled(False) + self.sbTlmOffset.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) + self.sbTlmOffset.setObjectName("sbTlmOffset") + self.gridLayout.addWidget(self.sbTlmOffset, 1, 2, 1, 1) + self.sbCmdOffsetPri = QtWidgets.QSpinBox(self.centralwidget) + self.sbCmdOffsetPri.setEnabled(False) + self.sbCmdOffsetPri.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) + self.sbCmdOffsetPri.setObjectName("sbCmdOffsetPri") + self.gridLayout.addWidget(self.sbCmdOffsetPri, 2, 2, 1, 1) + self.cbCmdHeaderVer = QtWidgets.QComboBox(self.centralwidget) + self.cbCmdHeaderVer.setObjectName("cbCmdHeaderVer") + self.cbCmdHeaderVer.addItem("") + self.cbCmdHeaderVer.addItem("") + self.cbCmdHeaderVer.addItem("") + self.gridLayout.addWidget(self.cbCmdHeaderVer, 2, 1, 1, 1) + self.sbCmdOffsetSec = QtWidgets.QSpinBox(self.centralwidget) + self.sbCmdOffsetSec.setEnabled(False) + self.sbCmdOffsetSec.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons) + self.sbCmdOffsetSec.setObjectName("sbCmdOffsetSec") + self.gridLayout.addWidget(self.sbCmdOffsetSec, 2, 3, 1, 1) self.label = QtWidgets.QLabel(self.centralwidget) self.label.setObjectName("label") self.gridLayout.addWidget(self.label, 0, 2, 1, 1) + self.label_6 = QtWidgets.QLabel(self.centralwidget) + self.label_6.setObjectName("label_6") + self.gridLayout.addWidget(self.label_6, 0, 3, 1, 1) self.verticalLayout.addLayout(self.gridLayout) self.horizontalLayout_2 = QtWidgets.QHBoxLayout() self.horizontalLayout_2.setSpacing(32) @@ -135,12 +157,19 @@ def retranslateUi(self, MainWindow): self.labelHomeTitle.setText(_translate("MainWindow", "CFS Ground System")) self.label_3.setText(_translate("MainWindow", "Selected IP Address")) self.comboBoxIpAddresses.setItemText(0, _translate("MainWindow", "All")) - self.label_4.setText(_translate("MainWindow", "Header version")) - self.cbHeaderVer.setItemText(0, _translate("MainWindow", "1")) - self.cbHeaderVer.setItemText(1, _translate("MainWindow", "2")) - self.cbHeaderVer.setItemText(2, _translate("MainWindow", "Custom")) - self.sbOffset.setToolTip(_translate("MainWindow", "

Offset (in bytes) to be *added to* existing offsets listed in tlm/cmd text files

")) - self.label.setText(_translate("MainWindow", "Offset (bytes)")) + self.label_4.setText(_translate("MainWindow", "Tlm header version")) + self.cbTlmHeaderVer.setItemText(0, _translate("MainWindow", "1")) + self.cbTlmHeaderVer.setItemText(1, _translate("MainWindow", "2")) + self.cbTlmHeaderVer.setItemText(2, _translate("MainWindow", "Custom")) + self.label_2.setText(_translate("MainWindow", "Cmd header version")) + self.sbTlmOffset.setToolTip(_translate("MainWindow", "

Offset (in bytes) to be added to existing offsets listed in telemetry text files

")) + self.sbCmdOffsetPri.setToolTip(_translate("MainWindow", "

Offset (in bytes) to be added after the primary header in a command packet

")) + self.cbCmdHeaderVer.setItemText(0, _translate("MainWindow", "1")) + self.cbCmdHeaderVer.setItemText(1, _translate("MainWindow", "2")) + self.cbCmdHeaderVer.setItemText(2, _translate("MainWindow", "Custom")) + self.sbCmdOffsetSec.setToolTip(_translate("MainWindow", "

Offset (in bytes) to be added after the secondary header in a command packet

")) + self.label.setText(_translate("MainWindow", "Offsets")) + self.label_6.setText(_translate("MainWindow", "(Hover for info)")) self.pushButtonStartTlm.setText(_translate("MainWindow", "Start Telemetry System")) self.pushButtonStartCmd.setText(_translate("MainWindow", "Start Command System")) self.label_5.setText(_translate("MainWindow", "*Read Guide-GroundSystem.txt for help")) diff --git a/common/shareddata.py b/common/shareddata.py index 6c8ef43..6c4fee1 100644 --- a/common/shareddata.py +++ b/common/shareddata.py @@ -22,4 +22,6 @@ # IMPORTANT: ANY class importing this module can read/write any of the data. # Use caution when read/writing data here. -offsetVal = 0 +tlmOffset = 0 +cmdOffsetPri = 0 +cmdOffsetSec = 0