diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 100f4ed..7221472 --- a/README.md +++ b/README.md @@ -1 +1,82 @@ -# SpikesLogger \ No newline at end of file +## Warnings! +- ### [python sucks](https://gitlab.com/TzintzeneT/dont-use-python), do not use python at home. +- ### Windows "defender" sucks, you can see that this app is no virus, it is open source. +# SpikesLogger + + +Welcome to the official SpikesLogger repo! +this app is the desktop part of the SpikesLogger real-time FRC logger. +The SpikesLogger uses the NetworkTables server on the roboRIO to log values from the robot to your computer. + +You can download the latest release from [here](https://github.com/Spikes-2212-Programming-Guild/SpikesLogger/releases), or build it yourself with the [commands below](#build-commands). +the SpikesLogger is designed to replace the System.out.println() statement you use every time you want to log some value when you run your code. +it is meant to be used for debugging but feel free to use it as you want. + +# Logging Values +1. _FIRST_, from your computer connect to your robot's network, then set the "server IP" in the app settings to your roborio's IP. +2. _SECOND_, as explained below, to log the values from your robot, you can use a couple of methods. + +**note:** make sure to not log the temp value in the app settings, otherwise it will not be logged. +if for some odd reason you want to log "SeaOttersAreSoFuckingCuteINeedThemInMyRoomRightNow", +you can change it to a different value. + +### Using SpikesLib2 +you can [install SpikesLib2](https://github.com/Spikes-2212-Programming-Guild/SpikesLib2#installation) +and use the built-in SpikesLogger using +``` +SpikesLogger sl = new SpikesLogger(); +``` +you can use the regular log function with: +``` +sl.log(value); +``` + +and you can use the log command (which will return a command): +``` +sl.logCommand(value); +``` +There are also the `logWithTimestamp` and `logWithTimestampCommand` +to log your values with a timestamp. + +### Using the NetworkTables Directly +Although not recommended, you can put the values that you want to log at a certain location in the NetworkTables, for example: SpikesLogger/output. +After that, you need to put that NetworkTables location at the "Logger Location" in the app settings and hit apply. + +**make sure** to not update the value periodically unless you want to log that same value periodically. + +this method is not recommended because you can accidentally put the value in the wrong place, +or do other stupid things you won't notice and will drive you insane. + + +### Creating Your Own Robot Logger +You can create your own robot logger in your preferred language (Java/C++/Python) to use with this desktop app. +You can take a look at the [SpikesLogger class](https://github.com/Spikes-2212-Programming-Guild/SpikesLib2/blob/dev/src/main/java/com/spikes2212/dashboard/SpikesLogger.java) +in SpikesLib2 for inspiration or just create one from scratch. +To do that, you'll need to make sure you are putting all of the values at the same location at the NetworkTables, +and you also need to put the "Logger Location" in the desktop app settings as that NetworkTables location. + + +# Build Commands: +### for linux: +```commandline + pyinstaller --onefile --add-data "SpikesLoggerSmallLogo.png:." SpikesLogger.py +``` +### for windows and mac: +```commandline + pyinstaller --onefile --windowed --icon=SpikesLoggerIcon.ico --add-data "SpikesLoggerSmallLogo.png:." SpikesLogger.py +``` + +## convert the .ui GUI file to Python +```commandline +pyuic6 LoggerGUI.ui -o LoggerGUI.py +``` + +## created using pain and FOSS +This app is licensed under the awesome GPLv3 licence, and written in Python (unfortunately). + +### other projects making this app possible: +- QT (PyQt6, Qt Designer) +- RobotPy (PyNetworkTables) +- pyinstaller (Compiling this) +- GIMP (logo design) +- PyCharm (because VSCode is broken and PyCharm is awesome unlike python) \ No newline at end of file diff --git a/images/Screenshot1.png b/images/Screenshot1.png new file mode 100644 index 0000000..bd60aac Binary files /dev/null and b/images/Screenshot1.png differ diff --git a/images/SpikesLoggerLogo.png b/images/SpikesLoggerLogo.png new file mode 100755 index 0000000..7d4b013 Binary files /dev/null and b/images/SpikesLoggerLogo.png differ diff --git a/images/SpikesLoggerLogo.xcf b/images/SpikesLoggerLogo.xcf new file mode 100755 index 0000000..60e9929 Binary files /dev/null and b/images/SpikesLoggerLogo.xcf differ diff --git a/src/EditConfig.py b/src/EditConfig.py new file mode 100755 index 0000000..980fff1 --- /dev/null +++ b/src/EditConfig.py @@ -0,0 +1,27 @@ +import json + + +def applyChanges(ip, save_location, logger_nt_location, temp_value): + conf_data = { + "logger-nt-location": logger_nt_location, + "save-location": save_location, + "serverip": ip, + "temp-value": temp_value + } + with open('../SpikesLog.conf', 'w') as file: + json.dump(conf_data, file) + print('config file saved') + + +def getData(): + try: + with open('../SpikesLog.conf', 'r') as json_file: + conf_data = json.load(json_file) + except: + conf_data = { + "logger-nt-location": "SpikesLogger/output", + "save-location": "logs", + "serverip": "255.255.255.255", + "temp-value": "SeaOttersAreSoFuckingCuteINeedThemInMyRoomRightNow" # Thanks to Mr. Borito our beloved alumn who went to FIRST service year + } + return conf_data diff --git a/src/LoggerGUI.py b/src/LoggerGUI.py new file mode 100755 index 0000000..185f3c0 --- /dev/null +++ b/src/LoggerGUI.py @@ -0,0 +1,196 @@ +# Form implementation generated from reading ui file 'LoggerGUI.ui' +# +# Created by: PyQt6 UI code generator 6.4.2 +# +# WARNING: Any manual changes made to this file will be lost when pyuic6 is +# run again. Do not edit this file unless you know what you are doing. + + +from PyQt6 import QtCore, QtGui, QtWidgets + + +class Ui_SpikesLoggerGuiWindow(object): + def setupUi(self, SpikesLoggerGuiWindow): + SpikesLoggerGuiWindow.setObjectName("SpikesLoggerGuiWindow") + SpikesLoggerGuiWindow.resize(844, 719) + self.centralwidget = QtWidgets.QWidget(parent=SpikesLoggerGuiWindow) + self.centralwidget.setObjectName("centralwidget") + self.gridLayout = QtWidgets.QGridLayout(self.centralwidget) + self.gridLayout.setObjectName("gridLayout") + self.tabWidget = QtWidgets.QTabWidget(parent=self.centralwidget) + self.tabWidget.setObjectName("tabWidget") + self.logsTab = QtWidgets.QWidget() + self.logsTab.setObjectName("logsTab") + self.horizontalLayout_3 = QtWidgets.QHBoxLayout(self.logsTab) + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.scrollArea = QtWidgets.QScrollArea(parent=self.logsTab) + self.scrollArea.setMaximumSize(QtCore.QSize(16777215, 16777215)) + self.scrollArea.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.SizeAdjustPolicy.AdjustIgnored) + self.scrollArea.setWidgetResizable(True) + self.scrollArea.setAlignment(QtCore.Qt.AlignmentFlag.AlignBottom|QtCore.Qt.AlignmentFlag.AlignJustify) + self.scrollArea.setObjectName("scrollArea") + self.ConsoleScrollArea = QtWidgets.QWidget() + self.ConsoleScrollArea.setGeometry(QtCore.QRect(0, 0, 802, 538)) + self.ConsoleScrollArea.setObjectName("ConsoleScrollArea") + self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.ConsoleScrollArea) + self.horizontalLayout_2.setObjectName("horizontalLayout_2") + self.logsConsole = QtWidgets.QLabel(parent=self.ConsoleScrollArea) + self.logsConsole.setAlignment(QtCore.Qt.AlignmentFlag.AlignLeading|QtCore.Qt.AlignmentFlag.AlignLeft|QtCore.Qt.AlignmentFlag.AlignTop) + self.logsConsole.setObjectName("logsConsole") + self.horizontalLayout_2.addWidget(self.logsConsole) + self.scrollArea.setWidget(self.ConsoleScrollArea) + self.horizontalLayout_3.addWidget(self.scrollArea) + self.tabWidget.addTab(self.logsTab, "") + self.settingsTab = QtWidgets.QWidget() + self.settingsTab.setObjectName("settingsTab") + self.verticalLayout = QtWidgets.QVBoxLayout(self.settingsTab) + self.verticalLayout.setSizeConstraint(QtWidgets.QLayout.SizeConstraint.SetDefaultConstraint) + self.verticalLayout.setObjectName("verticalLayout") + self.gridLayout_2 = QtWidgets.QGridLayout() + self.gridLayout_2.setObjectName("gridLayout_2") + self.TempValue = QtWidgets.QLineEdit(parent=self.settingsTab) + self.TempValue.setObjectName("TempValue") + self.gridLayout_2.addWidget(self.TempValue, 3, 2, 1, 1) + self.ServerIP = QtWidgets.QLineEdit(parent=self.settingsTab) + self.ServerIP.setObjectName("ServerIP") + self.gridLayout_2.addWidget(self.ServerIP, 2, 2, 1, 1) + self.label_3 = QtWidgets.QLabel(parent=self.settingsTab) + self.label_3.setObjectName("label_3") + self.gridLayout_2.addWidget(self.label_3, 1, 0, 1, 1) + self.label_4 = QtWidgets.QLabel(parent=self.settingsTab) + self.label_4.setObjectName("label_4") + self.gridLayout_2.addWidget(self.label_4, 2, 0, 1, 1) + self.networkTablesLoggerLocation = QtWidgets.QLineEdit(parent=self.settingsTab) + self.networkTablesLoggerLocation.setInputMask("") + self.networkTablesLoggerLocation.setObjectName("networkTablesLoggerLocation") + self.gridLayout_2.addWidget(self.networkTablesLoggerLocation, 0, 2, 1, 1) + self.label_5 = QtWidgets.QLabel(parent=self.settingsTab) + self.label_5.setObjectName("label_5") + self.gridLayout_2.addWidget(self.label_5, 3, 0, 1, 1) + self.label_2 = QtWidgets.QLabel(parent=self.settingsTab) + self.label_2.setObjectName("label_2") + self.gridLayout_2.addWidget(self.label_2, 0, 0, 1, 1) + self.ChooseDirPushButton = QtWidgets.QPushButton(parent=self.settingsTab) + font = QtGui.QFont() + font.setBold(False) + self.ChooseDirPushButton.setFont(font) + self.ChooseDirPushButton.setCursor(QtGui.QCursor(QtCore.Qt.CursorShape.ArrowCursor)) + self.ChooseDirPushButton.setLayoutDirection(QtCore.Qt.LayoutDirection.LeftToRight) + self.ChooseDirPushButton.setObjectName("ChooseDirPushButton") + self.gridLayout_2.addWidget(self.ChooseDirPushButton, 1, 2, 1, 1) + self.verticalLayout.addLayout(self.gridLayout_2) + self.applyChangesPushButton = QtWidgets.QPushButton(parent=self.settingsTab) + self.applyChangesPushButton.setObjectName("applyChangesPushButton") + self.verticalLayout.addWidget(self.applyChangesPushButton) + self.label_8 = QtWidgets.QLabel(parent=self.settingsTab) + self.label_8.setText("") + self.label_8.setObjectName("label_8") + self.verticalLayout.addWidget(self.label_8) + self.label_6 = QtWidgets.QLabel(parent=self.settingsTab) + font = QtGui.QFont() + font.setPointSize(20) + self.label_6.setFont(font) + self.label_6.setObjectName("label_6") + self.verticalLayout.addWidget(self.label_6) + self.label_7 = QtWidgets.QLabel(parent=self.settingsTab) + self.label_7.setWordWrap(True) + self.label_7.setObjectName("label_7") + self.verticalLayout.addWidget(self.label_7) + spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) + self.verticalLayout.addItem(spacerItem) + self.tabWidget.addTab(self.settingsTab, "") + self.gridLayout.addWidget(self.tabWidget, 9, 0, 1, 2) + self.horizontalLayout = QtWidgets.QHBoxLayout() + self.horizontalLayout.setObjectName("horizontalLayout") + self.StartPushButton = QtWidgets.QPushButton(parent=self.centralwidget) + self.StartPushButton.setObjectName("StartPushButton") + self.horizontalLayout.addWidget(self.StartPushButton) + self.PausePushButton = QtWidgets.QPushButton(parent=self.centralwidget) + self.PausePushButton.setObjectName("PausePushButton") + self.horizontalLayout.addWidget(self.PausePushButton) + self.SaveAndStopPushButton = QtWidgets.QPushButton(parent=self.centralwidget) + self.SaveAndStopPushButton.setAutoDefault(False) + self.SaveAndStopPushButton.setObjectName("SaveAndStopPushButton") + self.horizontalLayout.addWidget(self.SaveAndStopPushButton) + self.gridLayout.addLayout(self.horizontalLayout, 11, 0, 1, 2) + self.horizontalLayout_4 = QtWidgets.QHBoxLayout() + self.horizontalLayout_4.setObjectName("horizontalLayout_4") + spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Policy.Expanding, QtWidgets.QSizePolicy.Policy.Minimum) + self.horizontalLayout_4.addItem(spacerItem1) + self.label = QtWidgets.QLabel(parent=self.centralwidget) + font = QtGui.QFont() + font.setPointSize(14) + self.label.setFont(font) + self.label.setAlignment(QtCore.Qt.AlignmentFlag.AlignRight|QtCore.Qt.AlignmentFlag.AlignTrailing|QtCore.Qt.AlignmentFlag.AlignVCenter) + self.label.setObjectName("label") + self.horizontalLayout_4.addWidget(self.label) + self.StatusLabel = QtWidgets.QLabel(parent=self.centralwidget) + font = QtGui.QFont() + font.setPointSize(14) + self.StatusLabel.setFont(font) + self.StatusLabel.setObjectName("StatusLabel") + self.horizontalLayout_4.addWidget(self.StatusLabel) + self.gridLayout.addLayout(self.horizontalLayout_4, 0, 1, 1, 1) + SpikesLoggerGuiWindow.setCentralWidget(self.centralwidget) + self.menubar = QtWidgets.QMenuBar(parent=SpikesLoggerGuiWindow) + self.menubar.setGeometry(QtCore.QRect(0, 0, 844, 23)) + self.menubar.setObjectName("menubar") + self.menuSpikesLogger = QtWidgets.QMenu(parent=self.menubar) + self.menuSpikesLogger.setObjectName("menuSpikesLogger") + self.menuHelp = QtWidgets.QMenu(parent=self.menubar) + self.menuHelp.setObjectName("menuHelp") + SpikesLoggerGuiWindow.setMenuBar(self.menubar) + self.statusbar = QtWidgets.QStatusBar(parent=SpikesLoggerGuiWindow) + self.statusbar.setObjectName("statusbar") + SpikesLoggerGuiWindow.setStatusBar(self.statusbar) + self.actionOpen_file = QtGui.QAction(parent=SpikesLoggerGuiWindow) + self.actionOpen_file.setObjectName("actionOpen_file") + self.actionCreate_new_log = QtGui.QAction(parent=SpikesLoggerGuiWindow) + self.actionCreate_new_log.setObjectName("actionCreate_new_log") + self.actionAbout = QtGui.QAction(parent=SpikesLoggerGuiWindow) + self.actionAbout.setObjectName("actionAbout") + self.actionUpdate = QtGui.QAction(parent=SpikesLoggerGuiWindow) + self.actionUpdate.setObjectName("actionUpdate") + self.actionSource_code = QtGui.QAction(parent=SpikesLoggerGuiWindow) + self.actionSource_code.setObjectName("actionSource_code") + self.menuSpikesLogger.addAction(self.actionUpdate) + self.menuSpikesLogger.addSeparator() + self.menuSpikesLogger.addAction(self.actionSource_code) + self.menuSpikesLogger.addSeparator() + self.menuHelp.addAction(self.actionAbout) + self.menubar.addAction(self.menuSpikesLogger.menuAction()) + self.menubar.addAction(self.menuHelp.menuAction()) + + self.retranslateUi(SpikesLoggerGuiWindow) + self.tabWidget.setCurrentIndex(0) + QtCore.QMetaObject.connectSlotsByName(SpikesLoggerGuiWindow) + + def retranslateUi(self, SpikesLoggerGuiWindow): + _translate = QtCore.QCoreApplication.translate + SpikesLoggerGuiWindow.setWindowTitle(_translate("SpikesLoggerGuiWindow", "Spikes logger")) + self.logsConsole.setText(_translate("SpikesLoggerGuiWindow", "Click start to start logging...")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.logsTab), _translate("SpikesLoggerGuiWindow", "Logs")) + self.TempValue.setText(_translate("SpikesLoggerGuiWindow", "SeaOttersAreSoFuckingCuteINeedThemInMyRoomRightNow")) + self.ServerIP.setText(_translate("SpikesLoggerGuiWindow", "255.255.255.255")) + self.label_3.setText(_translate("SpikesLoggerGuiWindow", "Logs save location")) + self.label_4.setText(_translate("SpikesLoggerGuiWindow", "Server IP")) + self.networkTablesLoggerLocation.setText(_translate("SpikesLoggerGuiWindow", "SpikesLogger/output")) + self.label_5.setText(_translate("SpikesLoggerGuiWindow", "Temp value")) + self.label_2.setText(_translate("SpikesLoggerGuiWindow", "Logger location")) + self.ChooseDirPushButton.setText(_translate("SpikesLoggerGuiWindow", "/logs")) + self.applyChangesPushButton.setText(_translate("SpikesLoggerGuiWindow", "Apply")) + self.label_6.setText(_translate("SpikesLoggerGuiWindow", "How to use?")) + self.label_7.setText(_translate("SpikesLoggerGuiWindow", "
FIRST, make sure you are using a compatible logger on your robot (for example: SpikesLogger from SpikesLib). You can also put the value you want to log at the same location in the networktables as the Logger location in the settings above, although it is not recommended, and you need to make sure to not update the value periodically unless you want to log that same value periodically.
Enter your roborio IP and choose the location to save the logs to. after that you can start logging by pressing start, pause and save logs. You can change the temp value but make sure to set it to a value that is not likely to be logged.
To save the settings you can use the apply button.
")) + self.tabWidget.setTabText(self.tabWidget.indexOf(self.settingsTab), _translate("SpikesLoggerGuiWindow", "Settings")) + self.StartPushButton.setText(_translate("SpikesLoggerGuiWindow", "Start")) + self.PausePushButton.setText(_translate("SpikesLoggerGuiWindow", "Pause")) + self.SaveAndStopPushButton.setText(_translate("SpikesLoggerGuiWindow", "Stop and save")) + self.label.setText(_translate("SpikesLoggerGuiWindow", "Status:")) + self.StatusLabel.setText(_translate("SpikesLoggerGuiWindow", "off")) + self.menuSpikesLogger.setTitle(_translate("SpikesLoggerGuiWindow", "SpikesLogger")) + self.menuHelp.setTitle(_translate("SpikesLoggerGuiWindow", "Help")) + self.actionOpen_file.setText(_translate("SpikesLoggerGuiWindow", "Open log")) + self.actionCreate_new_log.setText(_translate("SpikesLoggerGuiWindow", "Create new log")) + self.actionAbout.setText(_translate("SpikesLoggerGuiWindow", "About")) + self.actionUpdate.setText(_translate("SpikesLoggerGuiWindow", "Update")) + self.actionSource_code.setText(_translate("SpikesLoggerGuiWindow", "Source code")) diff --git a/src/LoggerGUI.ui b/src/LoggerGUI.ui new file mode 100755 index 0000000..cefb758 --- /dev/null +++ b/src/LoggerGUI.ui @@ -0,0 +1,336 @@ + +