GUI: Can work offline for development
Build and Publish / build (push) Successful in 22s

This commit is contained in:
2025-06-10 08:45:10 +02:00
parent ef4dd537af
commit b2e32e294a
4 changed files with 45 additions and 12 deletions
+3 -1
View File
@@ -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 == "":
+2 -1
View File
@@ -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__()
+29 -9
View File
@@ -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()
+11 -1
View File
@@ -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")