diff --git a/client/brewpi.ui b/client/brewpi.ui index 5462c6c..e3e72b2 100644 --- a/client/brewpi.ui +++ b/client/brewpi.ui @@ -3675,6 +3675,8 @@ &File + + @@ -3726,6 +3728,22 @@ Stop + + + &Download Sud... + + + Save the running Sud's schedule to a local sud.json + + + + + &Upload Sud... + + + Replace the running Sud's schedule with a local sud.json + + diff --git a/client/brewpi_gui.py b/client/brewpi_gui.py index c0b16ad..d808d2e 100755 --- a/client/brewpi_gui.py +++ b/client/brewpi_gui.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 from main_window import Ui_MainWindow from PyQt5 import QtWidgets, QtGui +import json import sys from ws.client.ws_client import WsClient from ws.message import MessageDispatcherSync @@ -22,16 +23,20 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.msg_heater = self.msg_dispatch.msgio_get('Heater') self.msg_stirrer = self.msg_dispatch.msgio_get('Stirrer') self.msg_tempctrl = self.msg_dispatch.msgio_get('TempCtrl') + self.msg_sud = self.msg_dispatch.msgio_get('Sud') self.msg_pot.set_recv_handler(self.on_pot_changed) self.msg_sensor.set_recv_handler(self.on_sensor_changed) self.msg_heater.set_recv_handler(self.on_heater_changed) self.msg_stirrer.set_recv_handler(self.on_stirrer_changed) self.msg_tempctrl.set_recv_handler(self.on_tempctrl_changed) + self.msg_sud.set_recv_handler(self.on_sud_changed) self.setupUi(self) self.actionStart.triggered.connect(self.connect) self.actionStop.triggered.connect(self.disconnect) + self.actionSudDownload.triggered.connect(self.on_action_sud_download) + self.actionSudUpload.triggered.connect(self.on_action_sud_upload) self.Slider_pwr_soll.valueChanged.connect(self.on_slider_pwr_soll_changed) self.Slider_temp_soll.valueChanged.connect(self.on_slider_temp_soll_changed) self.Slider_speed_soll.valueChanged.connect(self.on_slider_stirrer_speed_soll_changed) @@ -48,6 +53,7 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.checkbox_heater_activate_initial_update = True self.checkbox_stirrer_activate_initial_update = True self.heatrate_soll_initial_update = True + self.sud_download_path = None def connect(self): self.slider_pwr_initial_update = True @@ -86,6 +92,24 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): print("on_checkbox_stirrer_activate_changed {}".format(value)) self.msg_stirrer.send({'Activate': int(value == 2)}) + def on_action_sud_download(self): + # Pick the destination up front, on the GUI thread - the actual + # write happens in on_sud_changed(), which runs off a worker thread + # and must not touch Qt (e.g. open a file dialog) itself. + path, _ = QtWidgets.QFileDialog.getSaveFileName(self, "Download Sud", filter="JSON files (*.json)") + if not path: + return + self.sud_download_path = path + self.msg_sud.send({'Download': True}) + + def on_action_sud_upload(self): + path, _ = QtWidgets.QFileDialog.getOpenFileName(self, "Upload Sud", filter="JSON files (*.json)") + if not path: + return + with open(path) as f: + data = json.load(f) + self.msg_sud.send({'Upload': data}) + def on_pot_changed(self, msg): print("on_pot_changed {}".format(msg)) for key in msg: @@ -160,6 +184,16 @@ class Window(QtWidgets.QMainWindow, Ui_MainWindow): self.Slider_speed_soll.setMinimum(int(submsg['Min'])) self.Slider_speed_soll.setMaximum(int(submsg['Max'])) + def on_sud_changed(self, msg): + print("on_sud_changed {}".format(msg)) + for key in msg: + if "Json" in key and self.sud_download_path: + with open(self.sud_download_path, 'w') as f: + json.dump(msg['Json'], f, indent='\t') + self.sud_download_path = None + elif "Name" in key: + self.statusBar().showMessage("Sud schedule updated: {}".format(msg['Name']), 5000) + def closeEvent(self, event): print("Exitting gracefully!") self.ws_client.disconnect() diff --git a/client/main_window.py b/client/main_window.py index 25c8556..8d002f0 100644 --- a/client/main_window.py +++ b/client/main_window.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'brewpi.ui' # -# Created by: PyQt5 UI code generator 5.15.10 +# Created by: PyQt5 UI code generator 5.15.11 # # WARNING: Any manual changes made to this file will be lost when pyuic5 is # run again. Do not edit this file unless you know what you are doing. @@ -1240,6 +1240,12 @@ class Ui_MainWindow(object): self.actionPause.setObjectName("actionPause") self.actionStop = QtWidgets.QAction(MainWindow) self.actionStop.setObjectName("actionStop") + self.actionSudDownload = QtWidgets.QAction(MainWindow) + self.actionSudDownload.setObjectName("actionSudDownload") + self.actionSudUpload = QtWidgets.QAction(MainWindow) + self.actionSudUpload.setObjectName("actionSudUpload") + self.menu_File.addAction(self.actionSudDownload) + self.menu_File.addAction(self.actionSudUpload) self.menubar.addAction(self.menu_File.menuAction()) self.menubar.addAction(self.menu_Help.menuAction()) self.toolBar.addAction(self.actionStart) @@ -1272,7 +1278,7 @@ class Ui_MainWindow(object): self.label_5.setText(_translate("MainWindow", "Power [W]")) self.label_7.setText(_translate("MainWindow", "State")) self.label_state.setText(_translate("MainWindow", "State")) - self.plainTextUri.setPlainText(_translate("MainWindow", "ws://localhost:8765")) + self.plainTextUri.setPlainText(_translate("MainWindow", "ws://brewpi:8765")) self.label_8.setText(_translate("MainWindow", "Host")) self.menu_File.setTitle(_translate("MainWindow", "&File")) self.menu_Help.setTitle(_translate("MainWindow", "&Help")) @@ -1284,3 +1290,7 @@ class Ui_MainWindow(object): self.actionPause.setToolTip(_translate("MainWindow", "Pause")) self.actionStop.setText(_translate("MainWindow", "Stop")) self.actionStop.setToolTip(_translate("MainWindow", "Stop")) + self.actionSudDownload.setText(_translate("MainWindow", "&Download Sud...")) + self.actionSudDownload.setToolTip(_translate("MainWindow", "Save the running Sud\'s schedule to a local sud.json")) + self.actionSudUpload.setText(_translate("MainWindow", "&Upload Sud...")) + self.actionSudUpload.setToolTip(_translate("MainWindow", "Replace the running Sud\'s schedule with a local sud.json"))