From b2e32e294a2ed30719e861abb65d18e08beb4d3a Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Tue, 10 Jun 2025 08:44:49 +0200 Subject: [PATCH] GUI: Can work offline for development --- gui/src/aaregui/main.py | 4 ++- gui/src/aaregui/main_window.py | 3 ++- gui/src/aaregui/threads/daq_worker.py | 38 ++++++++++++++++++++------- gui/src/aaregui/widgets/login.py | 12 ++++++++- 4 files changed, 45 insertions(+), 12 deletions(-) diff --git a/gui/src/aaregui/main.py b/gui/src/aaregui/main.py index d0f6216a..a8ef6e9e 100644 --- a/gui/src/aaregui/main.py +++ b/gui/src/aaregui/main.py @@ -32,7 +32,7 @@ if __name__ == "__main__": default_url = "http://x06sa-queue-01.psi.ch:5210" default_zmq_addr = "" case _: - default_url = "http://localhost:5210" + default_url = "" default_zmq_addr = "" # Add custom options as needed @@ -55,6 +55,8 @@ if __name__ == "__main__": parser.process(app) base_url = parser.value(urlOption) + if base_url == "": + base_url = None zmq_addr = parser.value(cameraZeroMQ) if zmq_addr == "": diff --git a/gui/src/aaregui/main_window.py b/gui/src/aaregui/main_window.py index bbfa74cf..7971037c 100644 --- a/gui/src/aaregui/main_window.py +++ b/gui/src/aaregui/main_window.py @@ -29,7 +29,8 @@ from aaregui.widgets.status_bar import StatusBar class MainWindow(QMainWindow): sample_geometry = Signal(SampleGeometryModel) - def __init__(self, base_url: str, token: str, + def __init__(self, base_url: str | None, + token: str, default_image: str | None, zmq_addr: str | None): super().__init__() diff --git a/gui/src/aaregui/threads/daq_worker.py b/gui/src/aaregui/threads/daq_worker.py index e60d2325..492d5ea5 100644 --- a/gui/src/aaregui/threads/daq_worker.py +++ b/gui/src/aaregui/threads/daq_worker.py @@ -7,16 +7,17 @@ from aaredaqlib.coordinate import SmargonCoordinate, Coordinate from aaredaqlib.raster_grid import RasterGridRequest from aaredaqlib.rotation_scan import RotationScanRequest -SPREADHSEET_FREQUENCY = 25 # Every 5 seconds +SPREADHSEET_FREQUENCY = 25 # Every 5 seconds + class DAQWorker(QObject): update = Signal(DAQStatusModel) spreadsheet = Signal(SampleShortInfoList) http_error = Signal(str) auth_error = Signal() - automated_scan_done = Signal(int, bool) # sample ID, success + automated_scan_done = Signal(int, bool) # sample ID, success - def __init__(self, base_url: str, token: str, parent=None): + def __init__(self, base_url: str | None, token: str, parent=None): super().__init__(parent) self.__token = token self.__base_url = base_url @@ -27,7 +28,6 @@ class DAQWorker(QObject): self.__timer.start() self.__counter = 0 - @Slot() def regular_update(self): if self.__counter % SPREADHSEET_FREQUENCY == 0: @@ -36,6 +36,9 @@ class DAQWorker(QObject): self.send_status_request() def send_status_request(self): + if self.__base_url is None: + return + request = QNetworkRequest(QUrl(f"{self.__base_url}/status")) request.setRawHeader(b"Authorization", f"Bearer {self.__token}".encode("utf-8")) reply = self.__net_manager.get(request) @@ -44,9 +47,9 @@ class DAQWorker(QObject): @staticmethod def handle_response(reply: QNetworkReply): if reply.error() == QNetworkReply.NetworkError.NoError: - response_data = reply.readAll().data().decode("utf-8") - reply.deleteLater() - return response_data + response_data = reply.readAll().data().decode("utf-8") + reply.deleteLater() + return response_data else: reply.deleteLater() raise RuntimeError(reply.errorString()) @@ -82,6 +85,10 @@ class DAQWorker(QObject): reply.deleteLater() def generic_post(self, url: str, body: str = ""): + if self.__base_url is None: + print(f"POST /{url}: {body}") + return + request = QNetworkRequest(QUrl(f"{self.__base_url}/{url}")) request.setRawHeader(b"Authorization", f"Bearer {self.__token}".encode("utf-8")) if str: @@ -90,6 +97,9 @@ class DAQWorker(QObject): reply.finished.connect(lambda: self.handle_req_response(reply)) def generic_put(self, url: str, body: str = ""): + if self.__base_url is None: + print(f"PUT /{url}: {body}") + return request = QNetworkRequest(QUrl(f"{self.__base_url}/{url}")) request.setRawHeader(b"Authorization", f"Bearer {self.__token}".encode("utf-8")) if str: @@ -98,6 +108,10 @@ class DAQWorker(QObject): reply.finished.connect(lambda: self.handle_req_response(reply)) def generic_delete(self, url: str): + if self.__base_url is None: + print(f"DELETE /{url}") + return + request = QNetworkRequest(QUrl(f"{self.__base_url}/{url}")) request.setRawHeader(b"Authorization", f"Bearer {self.__token}".encode("utf-8")) reply = self.__net_manager.deleteResource(request) @@ -176,6 +190,10 @@ class DAQWorker(QObject): @Slot() def load_spreadsheet(self): + if self.__base_url is None: + print(f"GET /tell/spreadsheet") + return + request = QNetworkRequest(QUrl(f"{self.__base_url}/tell/spreadsheet")) request.setRawHeader(b"Authorization", f"Bearer {self.__token}".encode("utf-8")) reply = self.__net_manager.get(request) @@ -198,6 +216,10 @@ class DAQWorker(QObject): @Slot(SampleShortInfo) def automated_scan(self, s: SampleShortInfo): + if self.__base_url is None: + print(f"POST /scan/auto: {s.model_dump_json()}") + return + request = QNetworkRequest(QUrl(f"{self.__base_url}/scan/auto")) request.setRawHeader(b"Authorization", f"Bearer {self.__token}".encode("utf-8")) request.setRawHeader(b"Content-Type", b"application/json") @@ -213,10 +235,8 @@ class DAQWorker(QObject): def abr_save(self): self.generic_post("beamline/save_abr_meas_pos") - @Slot(float, float) def beam_center_mark(self, x: float, y: float): - print(f"beam_center/mark?x={x}&y={y}") self.generic_post(f"beam_center/mark?x={x}&y={y}") @Slot() diff --git a/gui/src/aaregui/widgets/login.py b/gui/src/aaregui/widgets/login.py index 9036637d..7faa1169 100644 --- a/gui/src/aaregui/widgets/login.py +++ b/gui/src/aaregui/widgets/login.py @@ -1,15 +1,18 @@ import json import os +import jwt from PySide6.QtCore import Slot, QByteArray, QUrl, QUrlQuery from PySide6.QtNetwork import QNetworkAccessManager, QNetworkRequest, QNetworkReply from PySide6.QtWidgets import ( QDialog, QVBoxLayout, QLineEdit, QPushButton, QLabel, QHBoxLayout ) +from aaredaqlib.models import TokenData + class LoginDialog(QDialog): - def __init__(self, base_url: str): + def __init__(self, base_url: str | None): super().__init__() self.token = "" self.setWindowTitle("User Authentication") @@ -43,6 +46,13 @@ class LoginDialog(QDialog): @Slot() def authenticate(self): + if self.__base_url is None: + token_data = TokenData(sub=self.name_entry.text(), + staff=True, + session=15, + pgroups=["p16371", "p22233"]) + self.token = jwt.encode(token_data.model_dump(), "ABC123") + self.accept() network_manager = QNetworkAccessManager(self) request = QNetworkRequest(QUrl(f"{self.__base_url}/token")) request.setHeader(QNetworkRequest.KnownHeaders.ContentTypeHeader, "application/x-www-form-urlencoded")