diff --git a/.gitattributes b/.gitattributes index 4e8a4875..b0c5febf 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,3 +3,6 @@ # Declare files that will always have LF line endings on checkout. *.sh text eol=lf + +# Handle PNGs as binary +*.png binary diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..28419fdf --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,48 @@ +name: Build + +on: + push: + pull_request: + +jobs: + fsw: + runs-on: ubuntu-latest + container: + image: ivvitc/nos3-64:dev + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + - name: Update + run: apt-get update + - name: Install dependencies + run: apt-get install -y python3 docker docker.io + - name: prep + run: make prep + - name: config + run: make config + - name: build directory + run: mkdir ./fsw/build + - name: build + run: make build-fsw + + sim: + runs-on: ubuntu-latest + container: + image: ivvitc/nos3-64:dev + steps: + - uses: actions/checkout@v2 + with: + submodules: recursive + - name: Update + run: apt-get update + - name: Install dependencies + run: apt-get install -y python3 docker docker.io + - name: prep + run: make prep + - name: config + run: make config + - name: build directory + run: mkdir ./sims/build + - name: build + run: make build-sim diff --git a/Makefile b/Makefile index bc70c7ed..97c2885b 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ BUILDTYPE ?= debug INSTALLPREFIX ?= exe FSWBUILDDIR ?= $(CURDIR)/fsw/build +GSWBUILDDIR ?= $(CURDIR)/gsw/build SIMBUILDDIR ?= $(CURDIR)/sims/build export CFS_APP_PATH = ../components @@ -45,6 +46,11 @@ all: $(MAKE) sim $(MAKE) gsw +build-cryptolib: + mkdir -p $(GSWBUILDDIR) + cd $(GSWBUILDDIR) && cmake $(PREP_OPTS) -DSUPPORT=1 ../../components/cryptolib + $(MAKE) --no-print-directory -C $(GSWBUILDDIR) + build-fsw: ifeq($(FLIGHT_SOFTWARE), fprime) cd fsw/fprime/fprime-nos3 @@ -64,7 +70,7 @@ build-sim: $(MAKE) --no-print-directory -C $(SIMBUILDDIR) install checkout: - ./scripts/checkout.sh + ./scripts/docker_checkout.sh clean: $(MAKE) clean-fsw @@ -83,6 +89,7 @@ clean-sim: rm -rf sims/build clean-gsw: + rm -rf gsw/build rm -rf gsw/cosmos/build rm -rf /tmp/nos3 @@ -99,6 +106,7 @@ fsw: ./cfg/build/fsw_build.sh gsw: + ./scripts/docker_build_cryptolib.sh ./cfg/build/gsw_build.sh launch: @@ -123,3 +131,6 @@ stop: stop-gsw: ./scripts/stop_gsw.sh + +igniter: + ./scripts/igniter_launch.sh diff --git a/README.md b/README.md index ac21e10f..61a19ae8 100644 --- a/README.md +++ b/README.md @@ -7,15 +7,17 @@ The best source of documentation can be found at [the wiki](https://github.com/n ### Prerequisites Each of the applications listed below are required prior to performing the installation procedure: -* Option A +* Option A, you already use Linux * [Git 2.36+](https://git-scm.com/) * Linux with docker and docker compose installed -* Option B +* Option B, deployment of a virtual machine (VM) * [Git 2.36+](https://git-scm.com/) * [Vagrant 2.3.4+](https://www.vagrantup.com/) * [VirtualBox 7.0+](https://www.virtualbox.org/) ### Installing +Option B only. +Will provision a VM with all required packages installed to be used immediately. 1. Clone the repository `git clone https://github.com/nasa/nos3.git` 2. `cd nos3` 3. Clone the submodules `git submodule update --init --recursive` @@ -77,7 +79,11 @@ This project is licensed under the NOSA (NASA Open Source Agreement) License. Please report issues and request features on the GitHub tracking system - [NOS3 Issues](https://www.github.com/nasa/nos3/issues). ## Contributions -If you would like to contribute to the repository, please complete the [NOS3_Indv_CLA](./doc/NOS3_Indv_CLA.pdf) form and submit it to gsfc-softwarerequest@mail.nasa.gov with John.P.Lucas@nasa.gov copied. Next please create an issue capturing work to be done noting you intend to work it, a related branch, and submit a pull request when ready and we'll work to get it integrated. +If you would like to contribute to the repository, please complete this [NASA Form][def] and submit it to gsfc-softwarerequest@mail.nasa.gov with John.P.Lucas@nasa.gov CC'ed. +Next, please create an issue describing the work to be performed noting that you intend to work it, create a related branch, and submit a pull request when ready. When complete, we will review and work to get it integrated. ## Support If this project interests you or if you have any questions, please feel free to contact any developer directly or email `support@nos3.org`. + + +[def]: https://github.com/nasa/nos3/files/14578604/NOS3_Invd_CLA.pdf "NOS3 NASA Contributor Form PDF" \ No newline at end of file diff --git a/cfg/InOut/Inp_IPC.txt b/cfg/InOut/Inp_IPC.txt index e7f7a534..1e2bc0d8 100644 --- a/cfg/InOut/Inp_IPC.txt +++ b/cfg/InOut/Inp_IPC.txt @@ -1,15 +1,5 @@ <<<<<<<<<<<<<<< 42: InterProcess Comm Configuration File >>>>>>>>>>>>>>>> -17 ! Number of Sockets -********************************** Sample IPC ***************************** -TX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) -0 ! AC.ID for ACS mode -"State00.42" ! File name for WRITE or READ -SERVER ! Socket Role (SERVER,CLIENT,GMSEC_CLIENT) -fortytwo 4242 ! Server Host Name, Port -FALSE ! Allow Blocking (i.e. wait on RX) -FALSE ! Echo to stdout -1 ! Number of TX prefixes -"SC" ! Prefix 0 +16 ! Number of Sockets ********************************** RW 0 to 42 ***************************** RX ! IPC Mode (OFF,TX,RX,TXRX,ACS,WRITEFILE,READFILE) 0 ! AC.ID for ACS mode diff --git a/cfg/gui/.gitignore b/cfg/gui/.gitignore new file mode 100644 index 00000000..cb8a7669 --- /dev/null +++ b/cfg/gui/.gitignore @@ -0,0 +1,3 @@ +*.ui +*.ui.* +__pycache__ \ No newline at end of file diff --git a/cfg/gui/cfg_gui.ui b/cfg/gui/cfg_gui.ui new file mode 100644 index 00000000..02234ade --- /dev/null +++ b/cfg/gui/cfg_gui.ui @@ -0,0 +1,1198 @@ + + + Form + + + + 0 + 0 + 658 + 655 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + + Form + + + + + 0 + 0 + 661 + 661 + + + + QTabWidget::TabShape::Rounded + + + 0 + + + + Config + + + + + 130 + 20 + 421 + 26 + + + + Qt::AlignmentFlag::AlignCenter + + + true + + + None + + + + + + 550 + 20 + 94 + 26 + + + + Browse... + + + + + + 10 + 20 + 121 + 21 + + + + Current Config: + + + + + + 10 + 260 + 631 + 321 + + + + Spacecraft Config + + + + + 0 + 20 + 631 + 301 + + + + + + + + 0 + 0 + + + + true + + + Qt::ScrollBarPolicy::ScrollBarAlwaysOn + + + Qt::ScrollBarPolicy::ScrollBarAlwaysOff + + + true + + + + + 0 + 0 + 613 + 68 + + + + + 0 + 0 + + + + + QLayout::SizeConstraint::SetDefaultConstraint + + + + + + + + + + + 150 + -1 + 48 + 21 + + + + 1 + + + + + + + 10 + 60 + 631 + 181 + + + + Master Config + + + + + 0 + 20 + 631 + 161 + + + + + + + false + + + + + + + + + + 220 + 590 + 94 + 26 + + + + Save + + + + + + 330 + 590 + 94 + 26 + + + + Save As... + + + + + + 50 + 585 + 111 + 41 + + + + + + + true + + + + + + 480 + 585 + 131 + 41 + + + + + + + true + + + Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter + + + + + + Build + + + + + 10 + 120 + 631 + 491 + + + + Console Output + + + Qt::AlignmentFlag::AlignCenter + + + false + + + false + + + + + 0 + 20 + 631 + 471 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + true + + + + + + + 10 + 20 + 641 + 81 + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + 79 + 0 + 561 + 80 + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + 0 + 0 + 561 + 80 + + + + + + + All + + + + + + + All + + + + + + + FSW + + + + + + + CFG + + + + + + + SIM + + + + + + + SIM + + + + + + + GSW + + + + + + + FSW + + + + + + + GSW + + + + + + + + + + 0 + 0 + 81 + 41 + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + 0 + 0 + 81 + 41 + + + + + + + Build + + + Qt::AlignmentFlag::AlignCenter + + + + + + + + + + 0 + 40 + 81 + 41 + + + + QFrame::Shape::StyledPanel + + + QFrame::Shadow::Raised + + + + + 0 + 0 + 81 + 41 + + + + + + + Clean + + + Qt::AlignmentFlag::AlignCenter + + + + + + + + + + + Launch + + + + + 10 + 10 + 631 + 611 + + + + + + + + + 10 + 570 + 611 + 31 + + + + + 45 + + + + + Play + + + + ../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg + + + + + + + Pause + + + + ../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg + + + + + + + + + 10 + 10 + 611 + 41 + + + + + + + Launch + + + + + + + Stop + + + + + + + + + 10 + 60 + 611 + 451 + + + + NOS3 Time Driver + + + Qt::AlignmentFlag::AlignCenter + + + false + + + false + + + + + 0 + 20 + 611 + 431 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + true + + + + + + + 190 + 520 + 261 + 41 + + + + + + + + + + + + + Run For + + + + + Run Until + + + + + + + + + + + Qt::AlignmentFlag::AlignCenter + + + + + + + + + + + + diff --git a/cfg/gui/cfg_gui.ui.nIFTUJ b/cfg/gui/cfg_gui.ui.nIFTUJ new file mode 100644 index 00000000..6af78023 --- /dev/null +++ b/cfg/gui/cfg_gui.ui.nIFTUJ @@ -0,0 +1,1112 @@ + + + Form + + + + 0 + 0 + 655 + 655 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 170 + 170 + 170 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 127 + 127 + + + + + + + 255 + 255 + 255 + + + + + + + + Form + + + + + 0 + 0 + 661 + 661 + + + + QTabWidget::Rounded + + + 0 + + + + Config + + + + + 130 + 20 + 421 + 26 + + + + Qt::AlignCenter + + + true + + + None + + + + + + 550 + 20 + 94 + 26 + + + + Browse... + + + + + + 10 + 20 + 121 + 21 + + + + Current Config: + + + + + + 10 + 300 + 631 + 281 + + + + Spacecraft Config + + + + + 0 + 20 + 631 + 261 + + + + + + + QTextEdit::NoWrap + + + false + + + + + + + + + 150 + -1 + 48 + 21 + + + + 1 + + + + + + + 10 + 60 + 631 + 231 + + + + Master Config + + + + + 0 + 20 + 631 + 211 + + + + + + + false + + + + + + + + + + 220 + 590 + 94 + 26 + + + + Save + + + + + + 330 + 590 + 94 + 26 + + + + Save As... + + + + + + Build + + + + + 10 + 120 + 631 + 491 + + + + Console Output + + + false + + + false + + + + + 0 + 20 + 631 + 471 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + true + + + + + + + 110 + 20 + 421 + 81 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 79 + 0 + 341 + 80 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 340 + 80 + + + + + + + FSW + + + + + + + FSW + + + + + + + GSW + + + + + + + SIM + + + + + + + SIM + + + + + + + GSW + + + + + + + All + + + + + + + All + + + + + + + + + + 0 + 0 + 81 + 41 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 81 + 41 + + + + + + + Build + + + Qt::AlignCenter + + + + + + + + + + 0 + 40 + 81 + 41 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 81 + 41 + + + + + + + Clean + + + Qt::AlignCenter + + + + + + + + + + + Launch + + + + + 10 + 10 + 631 + 611 + + + + + + + + + 10 + 570 + 611 + 31 + + + + + 45 + + + + + Play + + + + ../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg + + + + + + + Pause + + + + ../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg + + + + + + + + + 10 + 10 + 611 + 41 + + + + + + + Launch + + + + + + + Stop + + + + + + + + + 10 + 60 + 611 + 451 + + + + Console Output + + + false + + + false + + + + + 0 + 20 + 611 + 431 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + + + true + + + + + + + 200 + 530 + 93 + 26 + + + + + Run For + + + + + Run Until + + + + + + + 290 + 530 + 181 + 26 + + + + + + + Qt::AlignCenter + + + + + + + + + diff --git a/cfg/gui/cfg_gui_main.py b/cfg/gui/cfg_gui_main.py new file mode 100644 index 00000000..232bfacb --- /dev/null +++ b/cfg/gui/cfg_gui_main.py @@ -0,0 +1,393 @@ +from pathlib import Path +from PySide6.QtWidgets import QWidget, QApplication, QFileDialog, QTextEdit, QPushButton, QDateTimeEdit, QLabel, QCheckBox, QVBoxLayout, QSizePolicy, QDoubleSpinBox, QLayout, QMessageBox +from PySide6.QtCore import QProcess, QDateTime +from PySide6.QtGui import QTextCharFormat, QPixmap +from cfg_gui_ui import Ui_Form +import sys, re, xmltodict, datetime, threading +import xml.etree.ElementTree as ET +import os + +# TODO: Update master xml sc-x-cfg filename if modified in sc config (in progress) +# TODO: disableButtons(), enableButtons() not working as intended due to the gnome-terminal thread handling the commands externally + +class cfg_gui(QWidget): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + self.ui = Ui_Form() + self.ui.setupUi(self) + self.setFixedSize(655, 655) + self.setWindowTitle("NOS3 Igniter - Version 0.0.1") + self.setWindowIcon(QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/nos3_original.png')) + + # globals + self.dateTimeEdit = QDateTimeEdit() + self.scConfigs = {} # Stores child configs {'index' : "filetext"} + self.prevButtonPressed = None # Tracks the last button pressed, used in buttonColor() + self.defaultStyleSheet = self.ui.pushButton_buildAll.styleSheet() # Saves default stylesheet to return button color to normal, buttonColor() + self.setup = 0 # Allows for switchConfig() to initially be called without calling saveText() + self.configNumTrack = 0 # Tracks the index of the previous SC config when switching to another index + self.defaultConfig = f'{os.path.dirname(os.path.abspath(__file__))}/../nos3-mission.xml' + self.config_path = self.defaultConfig + + # Config Tab + self.ui.pushButton_browse.clicked.connect(self.browseConfig) + self.ui.pushButton_save.clicked.connect(lambda: self.saveXML("save")) + self.ui.pushButton_saveAs.clicked.connect(lambda: self.saveXML("saveAs")) + self.ui.spinBox_configNumber.valueChanged.connect(lambda: self.switchConfig(self.ui.spinBox_configNumber.value())) + pixmap = QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/JSTAR-transparent_original.png') + self.ui.label_jstarLogo.setPixmap(pixmap) + pixmap = QPixmap(f'{os.path.dirname(os.path.abspath(__file__))}/resources/nos3_original.png') + self.ui.label_nos3Logo.setPixmap(pixmap) + + # Build Tab + self.ui.pushButton_buildAll.clicked.connect(lambda: self.build("all", self.ui.pushButton_buildAll)) + self.ui.pushButton_cfgBuild.clicked.connect(lambda: self.build("config", self.ui.pushButton_cfgBuild)) + self.ui.pushButton_fswBuild.clicked.connect(lambda: self.build("fsw", self.ui.pushButton_fswBuild)) + self.ui.pushButton_gswBuild.clicked.connect(lambda: self.build("gsw", self.ui.pushButton_gswBuild)) + self.ui.pushButton_simBuild.clicked.connect(lambda: self.build("sim", self.ui.pushButton_simBuild)) + self.ui.pushButton_cleanAll.clicked.connect(lambda: self.clean("all", self.ui.pushButton_cleanAll)) + self.ui.pushButton_fswClean.clicked.connect(lambda: self.clean("fsw", self.ui.pushButton_fswClean)) + self.ui.pushButton_gswClean.clicked.connect(lambda: self.clean("gsw", self.ui.pushButton_gswClean)) + self.ui.pushButton_simClean.clicked.connect(lambda: self.clean("sim", self.ui.pushButton_simClean)) + + # Launch Tab (Time Driver controls disabled) + #self.ui.pushButton_play.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Starting NOS3 Time Driver'"])) + self.ui.pushButton_play.setDisabled(1) + self.ui.pushButton_stop.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make stop")) + #self.ui.pushButton_pause.clicked.connect(lambda: self.startBashProcess(self.ui.textEdit_launchConsole, ["-lc", "echo '>> Pausing NOS3 Time Driver'"])) + self.ui.pushButton_pause.setDisabled(1) + self.ui.pushButton_launch.clicked.connect(lambda: self.gnome_terminal(self.ui.textEdit_launchConsole, "make launch")) + #self.ui.comboBox_run.currentIndexChanged.connect(self.run_ForUntil) + self.ui.comboBox_run.setDisabled(1) + self.ui.lineEdit_secondsEntry.setDisabled(1) + + # Load Default Config + self.reloadConfig(self.defaultConfig) + + # Replaces the textbox on launch tab with a date/time box and vice versa + def run_ForUntil(self): + index = self.ui.comboBox_run.currentIndex() + if index == 0: + self.ui.horizontalLayout_runForUntil.itemAt(1).widget().setParent(None) + self.ui.horizontalLayout_runForUntil.insertWidget(1, self.ui.lineEdit_secondsEntry) + self.ui.lineEdit_secondsEntry.setPlaceholderText("") + elif index == 1: + self.ui.horizontalLayout_runForUntil.itemAt(1).widget().setParent(None) + self.ui.horizontalLayout_runForUntil.insertWidget(1, self.ui.lineEdit_secondsEntry) + self.ui.lineEdit_secondsEntry.setPlaceholderText("Seconds") + elif index == 2: + self.ui.horizontalLayout_runForUntil.itemAt(1).widget().setParent(None) + self.currentTime = datetime.datetime.now() + self.dateTimeEdit.setMinimumDateTime(QDateTime(self.currentTime.year, self.currentTime.month, self.currentTime.day, self.currentTime.hour, self.currentTime.minute, self.currentTime.second, 0, 0)) + self.ui.horizontalLayout_runForUntil.insertWidget(1, self.dateTimeEdit) + + # Updates the currently saved xml dictionary (not actual xml file) for the currently selected spacecraft config when edited. TODO: change name of function + def saveText(self, layout:QLayout, config_value:int): + text = self.scConfigs[config_value] + filename = text.split('\n')[0] + childXml = xmltodict.parse(text.split('\n', 2)[2]) + + # TODO: change to dynamically pull apps/components from xml file or directory, but how? + applications = ['cf', 'ds', 'fm', 'lc', 'sc'] + components = ['adcs', 'cam', 'css', 'eps', 'fss', 'gps', 'imu', 'mag', 'radio', 'rw', 'sample', 'st', 'syn', 'torquer'] + + i = 0 + while layout.itemAt(i) != None: + widget = layout.itemAt(i).widget() + + # Handle filename + if isinstance(widget, QTextEdit): + widget:QTextEdit + filename = widget.toPlainText() + if "Filename:" not in filename: + filename = f'Filename: {filename}' + if "Filename: " not in filename: + filename = f'Filename: {filename.split(":")[1]}' + + # Handle checkboxes + elif isinstance(widget, QCheckBox): + widget:QCheckBox + text = widget.text().split(' ')[0] + if text in applications: + childXml['sc-1-config']['applications'][text]['enable'] = str(widget.isChecked()).lower() + elif text in components: + childXml['sc-1-config']['components'][text]['enable'] = str(widget.isChecked()).lower() + elif text == 'gui': + childXml['sc-1-config'][text]['enable'] = str(widget.isChecked()).lower() + + # Handle orbits + elif isinstance(widget, QDoubleSpinBox): + widget:QDoubleSpinBox + prefix = widget.prefix().split(' ')[0] + childXml['sc-1-config']['orbit'][prefix] = str(widget.value()) + + # Increment index + i += 1 + + combined = filename + '\n\n' + xmltodict.unparse(childXml) + self.scConfigs[config_value] = combined + + # Saves the master/child XML's edited in the GUI + def saveXML(self, saveType:str): + # saveType = "save" (overwrite) or "saveAs" (new) + + if saveType == "saveAs": + savePath, _ = QFileDialog.getSaveFileName(None, 'Directory', './cfg') + elif saveType == "save": + savePath = self.config_path + + # Grab master and save to xml + masterXml = xmltodict.parse(self.ui.textEdit_masterConfig.toPlainText()) + self.convert2xml(masterXml, savePath) + + # Now handle children + self.saveText(self.layout_, self.ui.spinBox_configNumber.value()-1) + + for child in self.scConfigs: + text = str(self.scConfigs[child]) + filename = text.split('\n')[0].split(' ')[1] + childXml = text.split('\n', 2)[2] + childXml = xmltodict.parse(childXml) + + # save under same directory as masterXml using filename parsed from textEdit + self.convert2xml(childXml, savePath.rsplit('/', 1)[0]+f'/{filename}') + + self.reloadConfig(self.config_path) + + # Loads the child config into the Spacecraft Config textbox + def switchConfig(self, value:int): + # value : index of spacecraft config in the order listed in the master XML + # Note: Parameter indexing starts at 1 + + # save edits made to config before viewing next one + if self.setup == 1: + self.saveText(self.layout_, self.configNumTrack) + self.configNumTrack = value-1 + else: + self.setup = 1 + + # setup layout to add item to + self.ui.scrollArea.setWidgetResizable(True) + self.ui.scrollAreaWidgetContents.setLayout(QVBoxLayout().layout()) + self.layout_ = self.ui.scrollAreaWidgetContents.layout() + self.layout_.setSpacing(12) + + # remove all items from SC Config window when switching index + while self.layout_.itemAt(0) != None: + child = self.layout_.itemAt(0).widget().setParent(None) + + # Now parse the xml and convert to widgets + value = value-1 + if value in self.scConfigs: + fileName = self.scConfigs[value].split('\n')[0] + childXML = self.scConfigs[value].split('\n')[2::] + childXML = ''.join(childXML) + childDict = xmltodict.parse(childXML) + + # child = sc-xxx-cfg + for child in childDict: + configTag = QTextEdit() + configTag.setText((fileName)) + configTag.setMinimumHeight(30) + self.layout_.addWidget(configTag) + + # child2 = applications | components | gui | orbit + for child2 in childDict[child]: + tag = QLabel() + tag.setText(child2.upper()+": ") + format = QTextCharFormat() + format.setFontUnderline(True) + tag.setFont(format.font()) + tag.setMinimumHeight(18) + self.layout_.addWidget(tag) + + if child2 in ['applications', 'components']: + + # child 3 = cf | ds | ... | adcs | cam | ... + for child3 in childDict[child][child2]: + enableTag = QCheckBox() + enableTag.setText(child3 + " enable ") + enableTag.setChecked(childDict[child][child2][child3]['enable'] == 'true') + enableTag.setMinimumHeight(18) + enableTag.sizePolicy().setVerticalPolicy(QSizePolicy.Expanding) + self.layout_.addWidget(enableTag) + + elif child2 == 'gui': + enableTag = QCheckBox() + enableTag.setText(child2 + " enable ") + enableTag.setChecked(childDict[child][child2]['enable'] == 'true') + self.layout_.addWidget(enableTag) + + elif child2 == 'orbit': + + # child3 = tipoff_x/y/z + for child3 in childDict[child][child2]: + orbitSpinBox = QDoubleSpinBox() + orbitSpinBox.setMinimum(-99.00) + orbitSpinBox.setMaximum(99.00) + orbitSpinBox.setValue(float(childDict[child][child2][child3])) + orbitSpinBox.setPrefix(f'{child3} = ') + self.layout_.addWidget(orbitSpinBox) + else: + # No SC configs in master XML file, or selected a SC XML as master + tag = QLabel() + tag.setText("*ERROR*\n\nMake sure you chose a master configuration file\n\n*ERROR*") + self.layout_.addWidget(tag) + + # Converts a dictionary to XML file, saved under the given filename/path + def convert2xml(self, attrDict:dict, fileName:str): + # ensure file is saved as xml + if fileName[-4::] != ".xml": + fileName += ".xml" + + # unparse dictionary to xml + with open(fileName, "w") as f: + xmltodict.unparse(attrDict, f, pretty=True) + f.close() + + # Opens file selection menu and calls parseXML() on the selected file + def browseConfig(self): + + # Clear SC Config window when selecting a new master config + if "layout_" in self.__dict__: + while self.layout_.itemAt(0) != None: + self.layout_.itemAt(0).widget().setParent(None) + + self.config_path, _ = QFileDialog.getOpenFileName(None, 'File', './cfg', "XML Files [ *.xml ]") + if self.config_path != "": + self.config_name = self.config_path.split("/")[-1] + self.ui.lineEdit_curConfig.setText(self.config_name) + self.parseXml(self.config_path) + + # Reloads the whole config after clicking save, allows you to change "sc-x-cfg" xml file + def reloadConfig(self, config_path): + if "layout_" in self.__dict__: + while self.layout_.itemAt(0) != None: + self.layout_.itemAt(0).widget().setParent(None) + + if config_path != "": + config_name = config_path.split("/")[-1] + self.ui.lineEdit_curConfig.setText(config_name) + self.parseXml(config_path) + + self.ui.spinBox_configNumber.setValue(1) + + # Parses Master and child XML files from the given file, updates text boxes accordingly + def parseXml(self, config_path): + + # Read Master + with open(config_path, 'r') as f: + self.ui.textEdit_masterConfig.setText(f.read()) + f.close() + + # Parse number of SC and SC filenames from master + i = 1 + self.sc_cfg_files = [] + childDict = {} + self.master_root = ET.parse(config_path).getroot() + for child in self.master_root: + if child.tag == "number-spacecraft": + self.ui.spinBox_configNumber.setMaximum(int(child.text)) + if re.match("sc-[0-9]+-cfg", child.tag): + childDict[child.tag] = child.text + + # Check for duplicate xml's + if child.text in self.sc_cfg_files: + QMessageBox.critical(self, "Error", "Using duplicate Spacecraft Config Files, Changes will not be saved correctly") + print("Duplicate SC Config file") + + self.sc_cfg_files.append(child.text) + i+=1 + + # Read Children + config_dir = str(config_path.rsplit('/', 1)[0]) + for i, child in enumerate(childDict): + if Path(f'{config_dir}/{childDict[child]}').is_file(): + filePath = f'{config_dir}/{childDict[child]}' + else: + raise FileNotFoundError(childDict[child]) + + with open(filePath, 'r') as f: + self.scConfigs[i] = f'Filename: {childDict[child]}\n\n{f.read()}' + f.close() + + # Update Spacecraft Config Text to first SC config listed in master config + self.switchConfig(1) + + # Test for gnome-terminal instead of bash, also uses startCommand() instead of start() + def gnome_terminal(self, textbox:QTextEdit, command:str): + process = QProcess() + + # `read line` is to hold the terminal open after execution, allows errors to be seen + process.startCommand(f'gnome-terminal --tab -- bash -c "{command}; echo Done. Press ENTER to close.; read line" ') + + process.readyReadStandardOutput.connect(lambda: textbox.append(process.readAllStandardOutput().data().decode())) + process.readyReadStandardError.connect(lambda: textbox.append(process.readAllStandardError().data().decode())) + + process.waitForFinished(msecs=-1) + textbox.append(f'>> {command}...') + + # Placeholder clean command + def clean(self, software:str, button:QPushButton): + textbox = self.ui.textEdit_buildConsole + if software == 'all': + command = f'make clean' + else: + command = f'make clean-{software}' + + self.buttonColor(button) + t1 = threading.Thread(target=self.thread_gnome(textbox, button, command), name='t1') + t1.start() + + # Placeholder build command, assumes make prep already ran, same with clean commands + def build(self, software:str, button:QPushButton): + textbox = self.ui.textEdit_buildConsole + if software == 'all': + command = f'make' + else: + command = f'make {software}' + + self.buttonColor(button) + t1 = threading.Thread(target=self.thread_gnome(textbox, button, command), name='t1') + t1.start() + + # Button/Bash function wrapper for threads + def thread_gnome(self, textbox:QTextEdit, button:QPushButton, command:str): + self.disableButtons(button) + self.gnome_terminal(textbox, command) + self.enableButtons(button) + + # Changes the color of the most recently pressed button to green and the last pressed button to default + def buttonColor(self, button:QPushButton): + if self.prevButtonPressed is not None: + self.prevButtonPressed.setStyleSheet(self.defaultStyleSheet) + button.setStyleSheet('QPushButton {background-color: green;}') + self.prevButtonPressed = button + + # Disable build/clean buttons while another is being ran (not working) + def disableButtons(self, button:QPushButton): + index = self.ui.gridLayout_buildCleanButtons.count()-1 + while index >= 0: + widget = self.ui.gridLayout_buildCleanButtons.itemAt(index).widget() + if widget != button: + widget.setDisabled(1) + index -= 1 + + # Enable build/clean buttons after process is done running (not working) + def enableButtons(self, button:QPushButton): + index = self.ui.gridLayout_buildCleanButtons.count()-1 + while index >= 0: + widget = self.ui.gridLayout_buildCleanButtons.itemAt(index).widget() + if widget != button: + widget.setEnabled(1) + index -= 1 + + +def main(): + app = QApplication(sys.argv) + win = cfg_gui() + win.show() + sys.exit(app.exec()) + +main() \ No newline at end of file diff --git a/cfg/gui/cfg_gui_ui.py b/cfg/gui/cfg_gui_ui.py new file mode 100644 index 00000000..32b50d49 --- /dev/null +++ b/cfg/gui/cfg_gui_ui.py @@ -0,0 +1,431 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'cfg_gui.ui' +## +## Created by: Qt User Interface Compiler version 6.7.0 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide6.QtCore import (QCoreApplication, QDate, QDateTime, QLocale, + QMetaObject, QObject, QPoint, QRect, + QSize, QTime, QUrl, Qt) +from PySide6.QtGui import (QBrush, QColor, QConicalGradient, QCursor, + QFont, QFontDatabase, QGradient, QIcon, + QImage, QKeySequence, QLinearGradient, QPainter, + QPalette, QPixmap, QRadialGradient, QTransform) +from PySide6.QtWidgets import (QApplication, QComboBox, QFrame, QGridLayout, + QGroupBox, QHBoxLayout, QLabel, QLayout, + QLineEdit, QPushButton, QScrollArea, QSizePolicy, + QSpinBox, QTabWidget, QTextEdit, QVBoxLayout, + QWidget) + +class Ui_Form(object): + def setupUi(self, Form): + if not Form.objectName(): + Form.setObjectName(u"Form") + Form.resize(658, 655) + palette = QPalette() + brush = QBrush(QColor(0, 0, 0, 255)) + brush.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.WindowText, brush) + brush1 = QBrush(QColor(255, 255, 255, 255)) + brush1.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.Button, brush1) + palette.setBrush(QPalette.Active, QPalette.Light, brush1) + palette.setBrush(QPalette.Active, QPalette.Midlight, brush1) + brush2 = QBrush(QColor(127, 127, 127, 255)) + brush2.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.Dark, brush2) + brush3 = QBrush(QColor(170, 170, 170, 255)) + brush3.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.Mid, brush3) + palette.setBrush(QPalette.Active, QPalette.Text, brush) + palette.setBrush(QPalette.Active, QPalette.BrightText, brush1) + palette.setBrush(QPalette.Active, QPalette.ButtonText, brush) + palette.setBrush(QPalette.Active, QPalette.Base, brush1) + palette.setBrush(QPalette.Active, QPalette.Window, brush1) + palette.setBrush(QPalette.Active, QPalette.Shadow, brush) + palette.setBrush(QPalette.Active, QPalette.AlternateBase, brush1) + brush4 = QBrush(QColor(255, 255, 220, 255)) + brush4.setStyle(Qt.SolidPattern) + palette.setBrush(QPalette.Active, QPalette.ToolTipBase, brush4) + palette.setBrush(QPalette.Active, QPalette.ToolTipText, brush) + brush5 = QBrush(QColor(0, 0, 0, 127)) + brush5.setStyle(Qt.SolidPattern) +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + palette.setBrush(QPalette.Active, QPalette.PlaceholderText, brush5) +#endif + palette.setBrush(QPalette.Active, QPalette.Accent, brush1) + palette.setBrush(QPalette.Inactive, QPalette.WindowText, brush) + palette.setBrush(QPalette.Inactive, QPalette.Button, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Light, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Midlight, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Dark, brush2) + palette.setBrush(QPalette.Inactive, QPalette.Mid, brush3) + palette.setBrush(QPalette.Inactive, QPalette.Text, brush) + palette.setBrush(QPalette.Inactive, QPalette.BrightText, brush1) + palette.setBrush(QPalette.Inactive, QPalette.ButtonText, brush) + palette.setBrush(QPalette.Inactive, QPalette.Base, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Window, brush1) + palette.setBrush(QPalette.Inactive, QPalette.Shadow, brush) + palette.setBrush(QPalette.Inactive, QPalette.AlternateBase, brush1) + palette.setBrush(QPalette.Inactive, QPalette.ToolTipBase, brush4) + palette.setBrush(QPalette.Inactive, QPalette.ToolTipText, brush) +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + palette.setBrush(QPalette.Inactive, QPalette.PlaceholderText, brush5) +#endif + palette.setBrush(QPalette.Inactive, QPalette.Accent, brush1) + palette.setBrush(QPalette.Disabled, QPalette.WindowText, brush2) + palette.setBrush(QPalette.Disabled, QPalette.Button, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Light, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Midlight, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Dark, brush2) + palette.setBrush(QPalette.Disabled, QPalette.Mid, brush3) + palette.setBrush(QPalette.Disabled, QPalette.Text, brush2) + palette.setBrush(QPalette.Disabled, QPalette.BrightText, brush1) + palette.setBrush(QPalette.Disabled, QPalette.ButtonText, brush2) + palette.setBrush(QPalette.Disabled, QPalette.Base, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Window, brush1) + palette.setBrush(QPalette.Disabled, QPalette.Shadow, brush) + palette.setBrush(QPalette.Disabled, QPalette.AlternateBase, brush1) + palette.setBrush(QPalette.Disabled, QPalette.ToolTipBase, brush4) + palette.setBrush(QPalette.Disabled, QPalette.ToolTipText, brush) + brush6 = QBrush(QColor(127, 127, 127, 127)) + brush6.setStyle(Qt.SolidPattern) +#if QT_VERSION >= QT_VERSION_CHECK(5, 12, 0) + palette.setBrush(QPalette.Disabled, QPalette.PlaceholderText, brush6) +#endif + palette.setBrush(QPalette.Disabled, QPalette.Accent, brush1) + Form.setPalette(palette) + self.tabWidget = QTabWidget(Form) + self.tabWidget.setObjectName(u"tabWidget") + self.tabWidget.setGeometry(QRect(0, 0, 661, 661)) + self.tabWidget.setTabShape(QTabWidget.TabShape.Rounded) + self.tab = QWidget() + self.tab.setObjectName(u"tab") + self.lineEdit_curConfig = QLineEdit(self.tab) + self.lineEdit_curConfig.setObjectName(u"lineEdit_curConfig") + self.lineEdit_curConfig.setGeometry(QRect(130, 20, 421, 26)) + self.lineEdit_curConfig.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.lineEdit_curConfig.setReadOnly(True) + self.pushButton_browse = QPushButton(self.tab) + self.pushButton_browse.setObjectName(u"pushButton_browse") + self.pushButton_browse.setGeometry(QRect(550, 20, 94, 26)) + self.label_curConfig = QLabel(self.tab) + self.label_curConfig.setObjectName(u"label_curConfig") + self.label_curConfig.setGeometry(QRect(10, 20, 121, 21)) + self.groupBox_scConfig = QGroupBox(self.tab) + self.groupBox_scConfig.setObjectName(u"groupBox_scConfig") + self.groupBox_scConfig.setGeometry(QRect(10, 260, 631, 321)) + self.horizontalLayoutWidget_6 = QWidget(self.groupBox_scConfig) + self.horizontalLayoutWidget_6.setObjectName(u"horizontalLayoutWidget_6") + self.horizontalLayoutWidget_6.setGeometry(QRect(0, 20, 631, 301)) + self.horizontalLayout_6 = QHBoxLayout(self.horizontalLayoutWidget_6) + self.horizontalLayout_6.setObjectName(u"horizontalLayout_6") + self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) + self.scrollArea = QScrollArea(self.horizontalLayoutWidget_6) + self.scrollArea.setObjectName(u"scrollArea") + sizePolicy = QSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.scrollArea.sizePolicy().hasHeightForWidth()) + self.scrollArea.setSizePolicy(sizePolicy) + self.scrollArea.setAutoFillBackground(True) + self.scrollArea.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOn) + self.scrollArea.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + self.scrollArea.setWidgetResizable(True) + self.scrollAreaWidgetContents = QWidget() + self.scrollAreaWidgetContents.setObjectName(u"scrollAreaWidgetContents") + self.scrollAreaWidgetContents.setGeometry(QRect(0, 0, 613, 68)) + sizePolicy1 = QSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Preferred) + sizePolicy1.setHorizontalStretch(0) + sizePolicy1.setVerticalStretch(0) + sizePolicy1.setHeightForWidth(self.scrollAreaWidgetContents.sizePolicy().hasHeightForWidth()) + self.scrollAreaWidgetContents.setSizePolicy(sizePolicy1) + self.verticalLayout_3 = QVBoxLayout(self.scrollAreaWidgetContents) + self.verticalLayout_3.setObjectName(u"verticalLayout_3") + self.verticalLayout_3.setSizeConstraint(QLayout.SizeConstraint.SetDefaultConstraint) + self.scrollArea.setWidget(self.scrollAreaWidgetContents) + + self.horizontalLayout_6.addWidget(self.scrollArea, 0, Qt.AlignmentFlag.AlignTop) + + self.spinBox_configNumber = QSpinBox(self.groupBox_scConfig) + self.spinBox_configNumber.setObjectName(u"spinBox_configNumber") + self.spinBox_configNumber.setGeometry(QRect(150, -1, 48, 21)) + self.spinBox_configNumber.setMinimum(1) + self.groupBox_masterConfig = QGroupBox(self.tab) + self.groupBox_masterConfig.setObjectName(u"groupBox_masterConfig") + self.groupBox_masterConfig.setGeometry(QRect(10, 60, 631, 181)) + self.horizontalLayoutWidget_5 = QWidget(self.groupBox_masterConfig) + self.horizontalLayoutWidget_5.setObjectName(u"horizontalLayoutWidget_5") + self.horizontalLayoutWidget_5.setGeometry(QRect(0, 20, 631, 161)) + self.horizontalLayout_5 = QHBoxLayout(self.horizontalLayoutWidget_5) + self.horizontalLayout_5.setObjectName(u"horizontalLayout_5") + self.horizontalLayout_5.setContentsMargins(0, 0, 0, 0) + self.textEdit_masterConfig = QTextEdit(self.horizontalLayoutWidget_5) + self.textEdit_masterConfig.setObjectName(u"textEdit_masterConfig") + self.textEdit_masterConfig.setReadOnly(False) + + self.horizontalLayout_5.addWidget(self.textEdit_masterConfig) + + self.pushButton_save = QPushButton(self.tab) + self.pushButton_save.setObjectName(u"pushButton_save") + self.pushButton_save.setGeometry(QRect(220, 590, 94, 26)) + self.pushButton_saveAs = QPushButton(self.tab) + self.pushButton_saveAs.setObjectName(u"pushButton_saveAs") + self.pushButton_saveAs.setGeometry(QRect(330, 590, 94, 26)) + self.label_nos3Logo = QLabel(self.tab) + self.label_nos3Logo.setObjectName(u"label_nos3Logo") + self.label_nos3Logo.setGeometry(QRect(50, 585, 111, 41)) + self.label_nos3Logo.setScaledContents(True) + self.label_jstarLogo = QLabel(self.tab) + self.label_jstarLogo.setObjectName(u"label_jstarLogo") + self.label_jstarLogo.setGeometry(QRect(480, 585, 131, 41)) + self.label_jstarLogo.setScaledContents(True) + self.label_jstarLogo.setAlignment(Qt.AlignmentFlag.AlignLeading|Qt.AlignmentFlag.AlignLeft|Qt.AlignmentFlag.AlignVCenter) + self.tabWidget.addTab(self.tab, "") + self.tab_2 = QWidget() + self.tab_2.setObjectName(u"tab_2") + self.groupBox_8 = QGroupBox(self.tab_2) + self.groupBox_8.setObjectName(u"groupBox_8") + self.groupBox_8.setGeometry(QRect(10, 120, 631, 491)) + self.groupBox_8.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.groupBox_8.setFlat(False) + self.groupBox_8.setCheckable(False) + self.textEdit_buildConsole = QTextEdit(self.groupBox_8) + self.textEdit_buildConsole.setObjectName(u"textEdit_buildConsole") + self.textEdit_buildConsole.setGeometry(QRect(0, 20, 631, 471)) + palette1 = QPalette() + palette1.setBrush(QPalette.Active, QPalette.Text, brush1) + palette1.setBrush(QPalette.Active, QPalette.Base, brush) + palette1.setBrush(QPalette.Inactive, QPalette.Text, brush1) + palette1.setBrush(QPalette.Inactive, QPalette.Base, brush) + self.textEdit_buildConsole.setPalette(palette1) + self.textEdit_buildConsole.setReadOnly(True) + self.frame_2 = QFrame(self.tab_2) + self.frame_2.setObjectName(u"frame_2") + self.frame_2.setGeometry(QRect(10, 20, 641, 81)) + self.frame_2.setFrameShape(QFrame.Shape.StyledPanel) + self.frame_2.setFrameShadow(QFrame.Shadow.Raised) + self.frame = QFrame(self.frame_2) + self.frame.setObjectName(u"frame") + self.frame.setGeometry(QRect(79, 0, 561, 80)) + self.frame.setFrameShape(QFrame.Shape.StyledPanel) + self.frame.setFrameShadow(QFrame.Shadow.Raised) + self.gridLayoutWidget_2 = QWidget(self.frame) + self.gridLayoutWidget_2.setObjectName(u"gridLayoutWidget_2") + self.gridLayoutWidget_2.setGeometry(QRect(0, 0, 561, 80)) + self.gridLayout_buildCleanButtons = QGridLayout(self.gridLayoutWidget_2) + self.gridLayout_buildCleanButtons.setObjectName(u"gridLayout_buildCleanButtons") + self.gridLayout_buildCleanButtons.setContentsMargins(0, 0, 0, 0) + self.pushButton_cleanAll = QPushButton(self.gridLayoutWidget_2) + self.pushButton_cleanAll.setObjectName(u"pushButton_cleanAll") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_cleanAll, 1, 0, 1, 1) + + self.pushButton_buildAll = QPushButton(self.gridLayoutWidget_2) + self.pushButton_buildAll.setObjectName(u"pushButton_buildAll") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_buildAll, 0, 0, 1, 1) + + self.pushButton_fswBuild = QPushButton(self.gridLayoutWidget_2) + self.pushButton_fswBuild.setObjectName(u"pushButton_fswBuild") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_fswBuild, 0, 2, 1, 1) + + self.pushButton_cfgBuild = QPushButton(self.gridLayoutWidget_2) + self.pushButton_cfgBuild.setObjectName(u"pushButton_cfgBuild") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_cfgBuild, 0, 1, 1, 1) + + self.pushButton_simClean = QPushButton(self.gridLayoutWidget_2) + self.pushButton_simClean.setObjectName(u"pushButton_simClean") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_simClean, 1, 4, 1, 1) + + self.pushButton_simBuild = QPushButton(self.gridLayoutWidget_2) + self.pushButton_simBuild.setObjectName(u"pushButton_simBuild") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_simBuild, 0, 4, 1, 1) + + self.pushButton_gswBuild = QPushButton(self.gridLayoutWidget_2) + self.pushButton_gswBuild.setObjectName(u"pushButton_gswBuild") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_gswBuild, 0, 3, 1, 1) + + self.pushButton_fswClean = QPushButton(self.gridLayoutWidget_2) + self.pushButton_fswClean.setObjectName(u"pushButton_fswClean") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_fswClean, 1, 2, 1, 1) + + self.pushButton_gswClean = QPushButton(self.gridLayoutWidget_2) + self.pushButton_gswClean.setObjectName(u"pushButton_gswClean") + + self.gridLayout_buildCleanButtons.addWidget(self.pushButton_gswClean, 1, 3, 1, 1) + + self.frame_3 = QFrame(self.frame_2) + self.frame_3.setObjectName(u"frame_3") + self.frame_3.setGeometry(QRect(0, 0, 81, 41)) + self.frame_3.setFrameShape(QFrame.Shape.StyledPanel) + self.frame_3.setFrameShadow(QFrame.Shadow.Raised) + self.verticalLayoutWidget = QWidget(self.frame_3) + self.verticalLayoutWidget.setObjectName(u"verticalLayoutWidget") + self.verticalLayoutWidget.setGeometry(QRect(0, 0, 81, 41)) + self.verticalLayout = QVBoxLayout(self.verticalLayoutWidget) + self.verticalLayout.setObjectName(u"verticalLayout") + self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.label_4 = QLabel(self.verticalLayoutWidget) + self.label_4.setObjectName(u"label_4") + self.label_4.setAlignment(Qt.AlignmentFlag.AlignCenter) + + self.verticalLayout.addWidget(self.label_4) + + self.frame_4 = QFrame(self.frame_2) + self.frame_4.setObjectName(u"frame_4") + self.frame_4.setGeometry(QRect(0, 40, 81, 41)) + self.frame_4.setFrameShape(QFrame.Shape.StyledPanel) + self.frame_4.setFrameShadow(QFrame.Shadow.Raised) + self.verticalLayoutWidget_2 = QWidget(self.frame_4) + self.verticalLayoutWidget_2.setObjectName(u"verticalLayoutWidget_2") + self.verticalLayoutWidget_2.setGeometry(QRect(0, 0, 81, 41)) + self.verticalLayout_2 = QVBoxLayout(self.verticalLayoutWidget_2) + self.verticalLayout_2.setObjectName(u"verticalLayout_2") + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.label_5 = QLabel(self.verticalLayoutWidget_2) + self.label_5.setObjectName(u"label_5") + self.label_5.setAlignment(Qt.AlignmentFlag.AlignCenter) + + self.verticalLayout_2.addWidget(self.label_5) + + self.tabWidget.addTab(self.tab_2, "") + self.tab_3 = QWidget() + self.tab_3.setObjectName(u"tab_3") + self.groupBox_control = QGroupBox(self.tab_3) + self.groupBox_control.setObjectName(u"groupBox_control") + self.groupBox_control.setGeometry(QRect(10, 10, 631, 611)) + self.horizontalLayoutWidget = QWidget(self.groupBox_control) + self.horizontalLayoutWidget.setObjectName(u"horizontalLayoutWidget") + self.horizontalLayoutWidget.setGeometry(QRect(10, 570, 611, 31)) + self.horizontalLayout = QHBoxLayout(self.horizontalLayoutWidget) + self.horizontalLayout.setSpacing(45) + self.horizontalLayout.setObjectName(u"horizontalLayout") + self.horizontalLayout.setContentsMargins(0, 0, 0, 0) + self.pushButton_play = QPushButton(self.horizontalLayoutWidget) + self.pushButton_play.setObjectName(u"pushButton_play") + icon = QIcon() + icon.addFile(u"../../../../../../../../usr/share/icons/Humanity/actions/24/gtk-media-play-ltr.svg", QSize(), QIcon.Normal, QIcon.Off) + self.pushButton_play.setIcon(icon) + + self.horizontalLayout.addWidget(self.pushButton_play) + + self.pushButton_pause = QPushButton(self.horizontalLayoutWidget) + self.pushButton_pause.setObjectName(u"pushButton_pause") + icon1 = QIcon() + icon1.addFile(u"../../../../../../../../usr/share/icons/Humanity/actions/24/media-playback-pause.svg", QSize(), QIcon.Normal, QIcon.Off) + self.pushButton_pause.setIcon(icon1) + + self.horizontalLayout.addWidget(self.pushButton_pause) + + self.horizontalLayoutWidget_2 = QWidget(self.groupBox_control) + self.horizontalLayoutWidget_2.setObjectName(u"horizontalLayoutWidget_2") + self.horizontalLayoutWidget_2.setGeometry(QRect(10, 10, 611, 41)) + self.horizontalLayout_2 = QHBoxLayout(self.horizontalLayoutWidget_2) + self.horizontalLayout_2.setObjectName(u"horizontalLayout_2") + self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0) + self.pushButton_launch = QPushButton(self.horizontalLayoutWidget_2) + self.pushButton_launch.setObjectName(u"pushButton_launch") + + self.horizontalLayout_2.addWidget(self.pushButton_launch) + + self.pushButton_stop = QPushButton(self.horizontalLayoutWidget_2) + self.pushButton_stop.setObjectName(u"pushButton_stop") + + self.horizontalLayout_2.addWidget(self.pushButton_stop) + + self.groupBox_9 = QGroupBox(self.groupBox_control) + self.groupBox_9.setObjectName(u"groupBox_9") + self.groupBox_9.setGeometry(QRect(10, 60, 611, 451)) + self.groupBox_9.setAlignment(Qt.AlignmentFlag.AlignCenter) + self.groupBox_9.setFlat(False) + self.groupBox_9.setCheckable(False) + self.textEdit_launchConsole = QTextEdit(self.groupBox_9) + self.textEdit_launchConsole.setObjectName(u"textEdit_launchConsole") + self.textEdit_launchConsole.setGeometry(QRect(0, 20, 611, 431)) + palette2 = QPalette() + palette2.setBrush(QPalette.Active, QPalette.Text, brush1) + palette2.setBrush(QPalette.Active, QPalette.Base, brush) + palette2.setBrush(QPalette.Inactive, QPalette.Text, brush1) + palette2.setBrush(QPalette.Inactive, QPalette.Base, brush) + self.textEdit_launchConsole.setPalette(palette2) + self.textEdit_launchConsole.setReadOnly(True) + self.horizontalLayoutWidget_3 = QWidget(self.groupBox_control) + self.horizontalLayoutWidget_3.setObjectName(u"horizontalLayoutWidget_3") + self.horizontalLayoutWidget_3.setGeometry(QRect(190, 520, 261, 41)) + self.horizontalLayout_runForUntil = QHBoxLayout(self.horizontalLayoutWidget_3) + self.horizontalLayout_runForUntil.setObjectName(u"horizontalLayout_runForUntil") + self.horizontalLayout_runForUntil.setContentsMargins(0, 0, 0, 0) + self.comboBox_run = QComboBox(self.horizontalLayoutWidget_3) + self.comboBox_run.addItem("") + self.comboBox_run.addItem("") + self.comboBox_run.addItem("") + self.comboBox_run.setObjectName(u"comboBox_run") + + self.horizontalLayout_runForUntil.addWidget(self.comboBox_run) + + self.lineEdit_secondsEntry = QLineEdit(self.horizontalLayoutWidget_3) + self.lineEdit_secondsEntry.setObjectName(u"lineEdit_secondsEntry") + self.lineEdit_secondsEntry.setAlignment(Qt.AlignmentFlag.AlignCenter) + + self.horizontalLayout_runForUntil.addWidget(self.lineEdit_secondsEntry) + + self.tabWidget.addTab(self.tab_3, "") + + self.retranslateUi(Form) + + self.tabWidget.setCurrentIndex(0) + + + QMetaObject.connectSlotsByName(Form) + # setupUi + + def retranslateUi(self, Form): + Form.setWindowTitle(QCoreApplication.translate("Form", u"Form", None)) + self.lineEdit_curConfig.setPlaceholderText(QCoreApplication.translate("Form", u"None", None)) + self.pushButton_browse.setText(QCoreApplication.translate("Form", u"Browse...", None)) + self.label_curConfig.setText(QCoreApplication.translate("Form", u"Current Config:", None)) + self.groupBox_scConfig.setTitle(QCoreApplication.translate("Form", u"Spacecraft Config", None)) + self.groupBox_masterConfig.setTitle(QCoreApplication.translate("Form", u"Master Config", None)) + self.pushButton_save.setText(QCoreApplication.translate("Form", u"Save", None)) + self.pushButton_saveAs.setText(QCoreApplication.translate("Form", u"Save As...", None)) + self.label_nos3Logo.setText("") + self.label_jstarLogo.setText("") + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), QCoreApplication.translate("Form", u"Config", None)) + self.groupBox_8.setTitle(QCoreApplication.translate("Form", u"Console Output", None)) + self.pushButton_cleanAll.setText(QCoreApplication.translate("Form", u"All", None)) + self.pushButton_buildAll.setText(QCoreApplication.translate("Form", u"All", None)) + self.pushButton_fswBuild.setText(QCoreApplication.translate("Form", u"FSW", None)) + self.pushButton_cfgBuild.setText(QCoreApplication.translate("Form", u"CFG", None)) + self.pushButton_simClean.setText(QCoreApplication.translate("Form", u"SIM", None)) + self.pushButton_simBuild.setText(QCoreApplication.translate("Form", u"SIM", None)) + self.pushButton_gswBuild.setText(QCoreApplication.translate("Form", u"GSW", None)) + self.pushButton_fswClean.setText(QCoreApplication.translate("Form", u"FSW", None)) + self.pushButton_gswClean.setText(QCoreApplication.translate("Form", u"GSW", None)) + self.label_4.setText(QCoreApplication.translate("Form", u"Build", None)) + self.label_5.setText(QCoreApplication.translate("Form", u"Clean", None)) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), QCoreApplication.translate("Form", u"Build", None)) + self.groupBox_control.setTitle("") + self.pushButton_play.setText(QCoreApplication.translate("Form", u"Play", None)) + self.pushButton_pause.setText(QCoreApplication.translate("Form", u"Pause", None)) + self.pushButton_launch.setText(QCoreApplication.translate("Form", u"Launch", None)) + self.pushButton_stop.setText(QCoreApplication.translate("Form", u"Stop", None)) + self.groupBox_9.setTitle(QCoreApplication.translate("Form", u"NOS3 Time Driver", None)) + self.comboBox_run.setItemText(0, "") + self.comboBox_run.setItemText(1, QCoreApplication.translate("Form", u"Run For", None)) + self.comboBox_run.setItemText(2, QCoreApplication.translate("Form", u"Run Until", None)) + + self.lineEdit_secondsEntry.setText("") + self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), QCoreApplication.translate("Form", u"Launch", None)) + # retranslateUi + diff --git a/cfg/gui/resources/JSTAR-transparent_original.png b/cfg/gui/resources/JSTAR-transparent_original.png new file mode 100644 index 00000000..5a988078 Binary files /dev/null and b/cfg/gui/resources/JSTAR-transparent_original.png differ diff --git a/cfg/gui/resources/nos3_original.png b/cfg/gui/resources/nos3_original.png new file mode 100644 index 00000000..a4a9a98d Binary files /dev/null and b/cfg/gui/resources/nos3_original.png differ diff --git a/cfg/nos3_defs/arch_build_custom.cmake b/cfg/nos3_defs/arch_build_custom.cmake index e2af60d2..a2919a52 100644 --- a/cfg/nos3_defs/arch_build_custom.cmake +++ b/cfg/nos3_defs/arch_build_custom.cmake @@ -28,18 +28,22 @@ add_compile_options( #-std=c99 # Target the C99 standard (without gcc extensions) #-pedantic # Issue all the warnings demanded by strict ISO C - -Wall # Warn about most questionable operations + #-Wall # Warn about most questionable operations #-Wstrict-prototypes # Warn about missing prototypes - -Wwrite-strings # Warn if not treating string literals as "const" - -Wpointer-arith # Warn about suspicious pointer operations + #-Wwrite-strings # Warn if not treating string literals as "const" + #-Wpointer-arith # Warn about suspicious pointer operations #-Werror # Treat warnings as errors (code should be clean) - -Wno-address-of-packed-member + #-Wno-address-of-packed-member # Build Specific -DBYTE_ORDER_LE -D_LINUX_OS_ -D_DEFAULT_SOURCE ) +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wstrict-prototypes -pedantic -Werror") +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wwrite-strings -Wpointer-arith -Wno-address-of-packed-member") +SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror") + if (CFE_SYSTEM_PSPNAME STREQUAL "nos-linux") # find itc cmake module path find_path(_ITC_CMAKE_MODULES_ diff --git a/cfg/nos3_defs/cpu1_cfe_es_startup.scr b/cfg/nos3_defs/cpu1_cfe_es_startup.scr index 324d5265..7a21cddb 100644 --- a/cfg/nos3_defs/cpu1_cfe_es_startup.scr +++ b/cfg/nos3_defs/cpu1_cfe_es_startup.scr @@ -1,3 +1,4 @@ +CFE_LIB, crypto, Crypto_SC_Init, CRYPTO, 0, 0, 0x0, 0; CFE_LIB, hwlib, hwlib_Init, HW_LIB, 0, 0, 0x0, 0; CFE_LIB, io_lib, IO_LibInit, IO_LIB, 0, 0, 0x0, 0; @@ -33,7 +34,6 @@ CFE_APP, generic_st, ST_AppMain, ST, CFE_APP, syn, SYN_AppMain, SYN, 72, 32768, 0x0, 0; CFE_LIB, cfs_lib, CFS_LibInit, CFS_LIB, 0, 0, 0x0, 0; -CFE_LIB, crypto, Crypto_TC_Init, CRYPTO, 0, 0, 0x0, 0; CFE_APP, cs, CS_AppMain, CS, 55, 16384, 0x0, 0; CFE_APP, hk, HK_AppMain, HK, 63, 16384, 0x0, 0; CFE_APP, hs, HS_AppMain, HS, 56, 16384, 0x0, 0; diff --git a/cfg/nos3_defs/tables/ds_filter_tbl.c b/cfg/nos3_defs/tables/ds_filter_tbl.c index c595d42a..de5a3afd 100644 --- a/cfg/nos3_defs/tables/ds_filter_tbl.c +++ b/cfg/nos3_defs/tables/ds_filter_tbl.c @@ -45,11 +45,12 @@ #include "cfe_msgids.h" #include "ds_msgids.h" +#include "sample_msgids.h" + /* #include "ci_lab_msgids.h" */ /* #include "to_lab_msgids.h" */ /* #include "cs_msgids.h" */ -/* #include "ds_msgids.h" */ /* #include "fm_msgids.h" */ /* #include "hk_msgids.h" */ /* #include "hs_msgids.h" */ @@ -196,11 +197,11 @@ DS_FilterTable_t DS_FilterTable = { {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}, {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}}}, /* Packet Index 014 */ - {/* .MessageID = */ CFE_SB_MSGID_RESERVED, + {/* .MessageID = */ CFE_SB_MSGID_WRAP_VALUE(SAMPLE_REQ_HK_MID), /* .Filter = */ {/* File table index, filter type, N, X, O */ - {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}, - {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}, + {FILE_ALL_APP_HK_PKTS, DS_BY_COUNT, 1, 1, 0}, + {FILE_ALL_APP_TLM_PKTS, DS_BY_COUNT, 1, 1, 0}, {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}, {DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED, DS_UNUSED}}}, /* Packet Index 015 */ diff --git a/cfg/nos3_defs/tables/sc_rts005.c b/cfg/nos3_defs/tables/sc_rts005.c index e2da32b8..a1d85837 100644 --- a/cfg/nos3_defs/tables/sc_rts005.c +++ b/cfg/nos3_defs/tables/sc_rts005.c @@ -8,10 +8,9 @@ #include "sc_msg.h" /* defines SC message structures */ /* Command Includes */ -#include "generic_radio_msg.h" -#include "generic_radio_msgids.h" -#include "sample_msg.h" -#include "sample_msgids.h" +#include "cam_app.h" +#include "generic_radio_app.h" +#include "sample_app.h" /* Custom table structure, modify as needed to add desired commands */ typedef struct @@ -20,6 +19,8 @@ typedef struct SAMPLE_Config_cmd_t cmd1; SC_RtsEntryHeader_t hdr2; GENERIC_RADIO_Proximity_cmd_t cmd2; + SC_RtsEntryHeader_t hdr3; + CAM_NoArgsCmd_t cmd3; } SC_RtsStruct005_t; /* Define the union to size the table correctly */ @@ -45,6 +46,10 @@ SC_RtsTable005_t SC_Rts005 = { .cmd2.CmdHeader = CFE_MSG_CMD_HDR_INIT(GENERIC_RADIO_CMD_MID, SC_MEMBER_SIZE(cmd2), GENERIC_RADIO_PROXIMITY_CC, 0x00), .cmd2.SCID = 0, .cmd2.Payload = {0x18, 0xA9, 0xC0, 0x00, 0x00, 0x05, 0x04, 0x00, 0x05, 0x00, 0x00, 0x00}, + + /* 3 - CAM NOOP */ + .hdr3.TimeTag = 1, + .cmd3.CmdHeader = CFE_MSG_CMD_HDR_INIT(CAM_CMD_MID, SC_MEMBER_SIZE(cmd3), CAM_NOOP_CC, 0x00), } }; diff --git a/cfg/nos3_defs/targets.cmake b/cfg/nos3_defs/targets.cmake index ddc442dd..b670344d 100644 --- a/cfg/nos3_defs/targets.cmake +++ b/cfg/nos3_defs/targets.cmake @@ -84,7 +84,7 @@ list(APPEND MISSION_GLOBAL_APPLIST # # Libraries # - #cryptolib + cryptolib hwlib io_lib # @@ -121,12 +121,17 @@ list(APPEND MISSION_GLOBAL_APPLIST # Create Application Platform Include List FOREACH(X ${MISSION_GLOBAL_APPLIST}) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/mission_inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/mission_inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/platform_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/platform_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/platform_inc) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/public_inc) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/public_inc) - LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/src) LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/src) + LIST(APPEND APPLICATION_PLATFORM_INC_LIST ${${X}_MISSION_DIR}/fsw/src) ENDFOREACH(X) # FT_INSTALL_SUBDIR indicates where the black box test data files (lua scripts) should diff --git a/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake b/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake index a062e7fc..80f34130 100644 --- a/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake +++ b/cfg/nos3_defs/toolchain-amd64-linux-gnu.cmake @@ -30,5 +30,5 @@ add_definitions(-DBYTE_ORDER_LE) add_definitions(-D_LINUX_OS_) set(CMAKE_POSITION_INDEPENDENT_CODE ON) -set(CI_TRANSPORT udp) -set(TO_TRANSPORT udp) +set(CI_TRANSPORT udp_tf) +set(TO_TRANSPORT udp) # Note udp_tf used for Transfer Frames required for CryptoLib diff --git a/cfg/sims/nos3-simulator.xml b/cfg/sims/nos3-simulator.xml index a451c739..1e2a065b 100644 --- a/cfg/sims/nos3-simulator.xml +++ b/cfg/sims/nos3-simulator.xml @@ -132,11 +132,14 @@ SAMPLE_PROVIDER + @@ -158,8 +161,8 @@ GPS42SOCKET fortytwo 4245 - 20 - 5 + 30 + 1 0 0 37 @@ -218,8 +221,8 @@ GENERIC_EPS_42_PROVIDER fortytwo 4283 - 20 - 5 + 30 + 1 0 @@ -299,8 +302,8 @@ fortytwo 4277 4278 - 20 - 5 + 30 + 1 0 0 @@ -325,8 +328,8 @@ fortytwo 4377 4378 - 20 - 5 + 30 + 1 0 1 @@ -351,8 +354,8 @@ fortytwo 4477 4478 - 20 - 5 + 30 + 1 0 2 @@ -376,8 +379,8 @@ GENERIC_CSS_42_PROVIDER fortytwo 4227 - 20 - 5 + 30 + 1 0 <42-css-scale-factor>1.0 @@ -405,8 +408,8 @@ GENERIC_TORQUER_42_PROVIDER fortytwo 4279 - 20 - 5 + 30 + 1 3 @@ -437,8 +440,8 @@ TRUTH42PROVIDER fortytwo 9999 - 20 - 5 + 30 + 1 0 0 @@ -462,8 +465,8 @@ GENERIC_FSS_42_PROVIDER fortytwo 4281 - 20 - 5 + 30 + 1 0 @@ -495,12 +498,19 @@ gsw - cosmos + + --> + + cosmos + 8010 + 6011 + @@ -540,8 +550,8 @@ GENERIC_IMU_42_PROVIDER fortytwo 4280 - 20 - 5 + 30 + 1 0 @@ -567,8 +577,8 @@ GENERIC_MAG_42_PROVIDER fortytwo 4234 - 20 - 5 + 30 + 1 0 @@ -594,8 +604,8 @@ GENERIC_STAR_TRACKER_PROVIDER fortytwo 4282 - 20 - 5 + 30 + 1 0 0 diff --git a/scripts/docker-compose.yml b/scripts/docker-compose.yml deleted file mode 100755 index 953c6e72..00000000 --- a/scripts/docker-compose.yml +++ /dev/null @@ -1,112 +0,0 @@ -version: '3.3' -services: - nos_engine_server_standalone: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json - working_dir: $SIM_BIN - tty: true - nos-time-driver: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos-time-driver - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-simulator-terminal: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-simulator-terminal - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-cam-simulator: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-cam-simulator - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-generic-reactionwheel-simulator: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-generic-reactionwheel-simulator - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-gps-simulator: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-gps-simulator - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - nos3-sample-simulator: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-sample-simulator - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - truth42sim: - volumes: - - '$SIM_DIR:$SIM_DIR' - network_mode: host - image: nos3 - command: $SIM_BIN/nos3-single-simulator truth42sim - working_dir: $SIM_BIN - depends_on: - - nos_engine_server_standalone - fsw: - volumes: - - '$FSW_BIN:$FSW_BIN' - network_mode: host - image: nos3 - command: $FSW_BIN/core-cpu1 -R PO - working_dir: $FSW_BIN - stdin_open: true - tty: true - sysctls: - - fs.mqueue.msg_max=500 - depends_on: - - nos_engine_server_standalone - fortytwo: - volumes: - - '/opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut' - - '/tmp/.X11-unix:/tmp/.X11-unix:ro' - network_mode: host - image: nos3 - command: /opt/nos3/42/42 NOS3InOut - working_dir: /opt/nos3/42 - tty: true - environment: - - DISPLAY=$DISPLAY - depends_on: - - nos_engine_server_standalone - cosmos: - volumes: - - '/home/nos3/Desktop/github-nos3/gsw/cosmos:/cosmos/cosmos' - - '/home/nos3/Desktop/github-nos3/components/:/COMPONENTS' - - '/tmp/.X11-unix:/tmp/.X11-unix:ro' - network_mode: host - image: ballaerospace/cosmos - command: /bin/bash -c 'ruby Launcher -c nos3_launcher.txt --system nos3_system.txt && true' # true is necessary to avoid setpgrp error - working_dir: /cosmos/cosmos - tty: true - environment: - - DISPLAY=$DISPLAY - - QT_X11_NO_MITSHM=1 diff --git a/scripts/docker_build_cryptolib.sh b/scripts/docker_build_cryptolib.sh new file mode 100755 index 00000000..63126da2 --- /dev/null +++ b/scripts/docker_build_cryptolib.sh @@ -0,0 +1,31 @@ +#!/bin/bash -i +# +# Convenience script for NOS3 development +# Use with the Dockerfile in the deployment repository +# https://github.com/nasa-itc/deployment +# + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh + +# Check that local NOS3 directory exists +if [ ! -d $USER_NOS3_DIR ]; then + echo "" + echo " Need to run make prep first!" + echo "" + exit 1 +fi + +# Check that configure build directory exists +if [ ! -d $BASE_DIR/cfg/build ]; then + echo "" + echo " Need to run make config first!" + echo "" + exit 1 +fi + +# Make ground software build directory +mkdir -p $BASE_DIR/gsw/build + +# Build +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR --name "nos_build_cryptolib" -w $BASE_DIR $DBOX make -j$NUM_CPUS build-cryptolib diff --git a/scripts/checkout.sh b/scripts/docker_checkout.sh similarity index 81% rename from scripts/checkout.sh rename to scripts/docker_checkout.sh index 7b6d80b2..92c716f8 100755 --- a/scripts/checkout.sh +++ b/scripts/docker_checkout.sh @@ -21,11 +21,10 @@ echo "" # Replace `--tab` with `--window-with-profile=KeepOpen` once you've created this gnome-terminal profile manually #echo "42..." -#cd /opt/nos3/42/ -#rm -rf NOS3InOut -#cp -r $BASE_DIR/sims/cfg/InOut /opt/nos3/42/NOS3InOut +#rm -rf $USER_NOS3_DIR/42/NOS3InOut +#cp -r $BASE_DIR/cfg/build/InOut $USER_NOS3_DIR/42/NOS3InOut #xhost +local:* -#gnome-terminal --window-with-profile=KeepOpen --title="42" -- $DFLAGS -e DISPLAY=$DISPLAY -v /opt/nos3/42/NOS3InOut:/opt/nos3/42/NOS3InOut -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w /opt/nos3/42 -t $DBOX /opt/nos3/42/42 NOS3InOut +#gnome-terminal --tab --title=$SC_NUM" - 42" -- $DFLAGS -e DISPLAY=$DISPLAY -v $USER_NOS3_DIR:$USER_NOS3_DIR -v /tmp/.X11-unix:/tmp/.X11-unix:ro --name $SC_NUM"_fortytwo" -h fortytwo --network=$SC_NETNAME -w $USER_NOS3_DIR/42 -t $DBOX $USER_NOS3_DIR/42/42 NOS3InOut #echo "" echo "NOS Core..." @@ -48,6 +47,7 @@ gnome-terminal --tab --title="Generic Star Tracker" -- $DFLAGS -v $SIM_DIR:$SIM_ # Rename for your checkout under test to allow checkout gnome-terminal --tab --title="FPrime" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_sample_checkout" --network=$SC_NETNAME -w $BASE_DIR $DBOX ./scripts/fsw_fprime_launch.sh +#gnome-terminal --title="Sample Checkout" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_sample_checkout" --network=$SC_NETNAME -w $BASE_DIR $DBOX ./components/sample/support/build/sample_checkout echo "" diff --git a/scripts/docker_launch.sh b/scripts/docker_launch.sh index 5243c866..5d1caec7 100755 --- a/scripts/docker_launch.sh +++ b/scripts/docker_launch.sh @@ -101,6 +101,10 @@ do # Debugging # Replace `--tab` with `--window-with-profile=KeepOpen` once you've created this gnome-terminal profile manually + echo $SC_NUM " - CryptoLib..." + gnome-terminal --tab --title=$SC_NUM" - CryptoLib" -- $DFLAGS -v $BASE_DIR:$BASE_DIR --name $SC_NUM"_cryptolib" --network=$SC_NETNAME --network-alias=cryptolib -w $BASE_DIR/gsw/build $DBOX ./support/standalone + echo "" + echo $SC_NUM " - Simulators..." cd $SIM_BIN gnome-terminal --tab --title=$SC_NUM" - NOS Engine Server" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_nos_engine_server" -h nos_engine_server --network=$SC_NETNAME -w $SIM_BIN $DBOX /usr/bin/nos_engine_server_standalone -f $SIM_BIN/nos_engine_server_config.json @@ -126,9 +130,6 @@ do gnome-terminal --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim gnome-terminal --tab --title=$SC_NUM" - StarTrk Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_startrk_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_star_tracker_sim gnome-terminal --tab --title=$SC_NUM" - Torquer Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_torquer_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE generic_torquer_sim - - # Note: Can keep open if desired after a new gnome-profile is manually created - #gnome-terminal --window-with-profile=KeepOpen --tab --title=$SC_NUM" - Sample Sim" -- $DFLAGS -v $SIM_DIR:$SIM_DIR --name $SC_NUM"_sample_sim" --network=$SC_NETNAME -w $SIM_BIN $DBOX ./nos3-single-simulator $SC_CFG_FILE sample_sim echo "" done diff --git a/scripts/env.sh b/scripts/env.sh index c077a426..f99dc99e 100755 --- a/scripts/env.sh +++ b/scripts/env.sh @@ -41,7 +41,7 @@ OPENC3_PATH=$OPENC3_DIR/openc3.sh DNETWORK="docker network" #fi -#DBOX="ivvitc/nos3-64:20240306" +#DBOX="ivvitc/nos3-64:20240430" DBOX="ivvitc/nos3-64:fprime" # Debugging diff --git a/scripts/gsw_cosmos_build.sh b/scripts/gsw_cosmos_build.sh index 53085664..84d591ac 100755 --- a/scripts/gsw_cosmos_build.sh +++ b/scripts/gsw_cosmos_build.sh @@ -7,14 +7,11 @@ CFG_BUILD_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd SCRIPT_DIR=$CFG_BUILD_DIR/../../scripts source $SCRIPT_DIR/env.sh -# Debugging -#echo "Script directory = " $SCRIPT_DIR -#echo "Base directory = " $BASE_DIR -#exit - -#echo "Make /tmp folders..." -#mkdir /tmp/data 2> /dev/null -#mkdir /tmp/data/hk 2> /dev/null -#mkdir /tmp/uplink 2> /dev/null - echo "COSMOS build..." +mkdir $GSW_DIR/COMPONENTS 2> /dev/null +rm -r $GSW_DIR/COMPONENTS/* 2> /dev/null +for i in $(find $BASE_DIR/components/ -name "gsw" -type d) +do + #echo "$i" + cp -r $i/* $GSW_DIR/COMPONENTS/ +done diff --git a/scripts/igniter_launch.sh b/scripts/igniter_launch.sh new file mode 100755 index 00000000..bbe225d1 --- /dev/null +++ b/scripts/igniter_launch.sh @@ -0,0 +1,13 @@ +#!/bin/bash -i +# +# Convenience script for NOS# development + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +source $SCRIPT_DIR/env.sh +echo "" +echo "" + +cd $BASE_DIR +python3 $BASE_DIR/cfg/gui/cfg_gui_main.py & +echo "" +echo "" \ No newline at end of file diff --git a/scripts/prepare.sh b/scripts/prepare.sh index fd9942cc..eb492703 100755 --- a/scripts/prepare.sh +++ b/scripts/prepare.sh @@ -27,63 +27,39 @@ mkdir $USER_NOS3_DIR/42 2> /dev/null echo "" echo "" -# while read_xml; do -# if [[ $ENTITY = "fsw" ]]; then -# FLIGHT_SOFTWARE=$CONTENT -# break -# fi -# done < ./cfg/nos3-mission.xml - -# echo "Using Flight Software: ${FLIGHT_SOFTWARE}" -# echo "" -# echo "" - -# if [[ $FLIGHT_SOFTWARE = "fprime" ]] ; then - - echo "Preparing FPrime FSW" - echo $DFLAGS_CPUS $DBOX - $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR --name "fprime_prepare" -w $BASE_DIR $DBOX ./scripts/prep_fprime.sh - - echo "" - echo "" - -# echo "Prepare nos3 docker container..." -# $DCALL image pull $DBOX -# echo "" -# echo "" +echo "Preparing FPrime FSW" +echo $DFLAGS_CPUS $DBOX +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR --name "fprime_prepare" -w $BASE_DIR $DBOX ./scripts/prep_fprime.sh +echo "" +echo "" -# echo "Prepare 42..." -# cd $USER_NOS3_DIR -# git clone https://github.com/nasa-itc/42.git --depth 1 -b nos3-main -# cd $USER_NOS3_DIR/42 -# $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR -w $USER_NOS3_DIR/42 --name "nos3_42_build" $DBOX make -# echo "" -# echo "" -# fi +echo "Clone openc3-cosmos into local user directory..." +cd $USER_NOS3_DIR +git clone https://github.com/nasa-itc/openc3-nos3.git --depth 1 -b main $USER_NOS3_DIR/cosmos +echo "" +echo "" -# if [[ $FLIGHT_SOFTWARE = "cfs" ]] ; then - echo "Clone openc3-cosmos into local user directory..." - cd $USER_NOS3_DIR - git clone https://github.com/nasa-itc/openc3-nos3.git --depth 1 -b main $USER_NOS3_DIR/cosmos - git reset --hard - echo "" - echo "" +echo "Prepare cosmos docker container..." +$DCALL image pull ballaerospace/cosmos:4.5.0 +echo "" +echo "" - echo "Prepare cosmos docker container..." - $DCALL image pull ballaerospace/cosmos:4.5.0 - echo "" - echo "" +echo "Prepare nos3 docker container..." +$DCALL image pull $DBOX +echo "" +echo "" - echo "Prepare nos3 docker container..." - $DCALL image pull $DBOX - echo "" - echo "" +echo "Prepare 42..." +cd $USER_NOS3_DIR +git clone https://github.com/nasa-itc/42.git --depth 1 -b nos3-main +cd $USER_NOS3_DIR/42 +$DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR -w $USER_NOS3_DIR/42 --name "nos3_42_build" $DBOX make +echo "" +echo "" - echo "Prepare 42..." - cd $USER_NOS3_DIR - git clone https://github.com/nasa-itc/42.git --depth 1 -b nos3-main - cd $USER_NOS3_DIR/42 - $DFLAGS_CPUS -v $BASE_DIR:$BASE_DIR -v $USER_NOS3_DIR:$USER_NOS3_DIR -w $USER_NOS3_DIR/42 --name "nos3_42_build" $DBOX make - echo "" - echo "" -# fi +echo "Prepare Igniter..." +pip3 install pyside6 xmltodict +cd $BASE_DIR +python3 $BASE_DIR/cfg/gui/cfg_gui_main.py & +echo "" +echo ""