diff --git a/daq_main_common.py b/daq_main_common.py index 809301e9..77fe3115 100755 --- a/daq_main_common.py +++ b/daq_main_common.py @@ -1,26 +1,28 @@ +import _thread +import atexit +import json +import logging +import os import string import sys -import os import time -import _thread +import traceback + +import beamline_lib +import beamline_support +import config_params import daq_lib import daq_utils import det_lib -import beamline_support -import beamline_lib -from start_bs import plt -import config_params -import atexit -import traceback +from beamline_lib import * +from daq_lib import * #imports to get useful things into namespace for server from daq_macros import * -from daq_lib import * -from robot_lib import * -from beamline_lib import * from gov_lib import setGovRobot +from robot_lib import * +from start_bs import gov_robot, plt -import logging logger = logging.getLogger(__name__) sitefilename = "" @@ -29,10 +31,68 @@ immediate_command_list = [] z = 25 +def setGovState(state): + setGovRobot(gov_robot, state) + + +functions = [anneal, + set_beamsize, + importSpreadsheet, + mvaDescriptor, + setTrans, + loop_center_xrec, + autoRasterLoop, + snakeRaster, + ispybLib.insertRasterResult, + backlightBrighter, + backlightDimmer, + changeImageCenterHighMag, + changeImageCenterLowMag, + center_on_click, + runDCQueue, + warmupGripper, + dryGripper, + enableDewarTscreen, + parkGripper, + stopDCQueue, + continue_data_collection, + mountSample, + unmountSample, + reprocessRaster, + fastDPNodes, + spotNodes, + unmountCold, + openPort, + set_beamcenter, + closePorts, + clearMountedSample, + recoverRobot, + rebootEMBL, + restartEMBL, + openGripper, + closeGripper, + homePins, + setSlit1X, + setSlit1Y, + testRobot, + setGovState] + +whitelisted_functions: "Dict[str, Callable]" = { + func.__name__: func for func in functions +} def execute_command(command_s): - logger.info('executing command: %s' % command_s) - exec(command_s) + logger.info("executing command: %s" % command_s) + try: + command: "dict[str, Any]" = json.loads(command_s) + func = whitelisted_functions[command["function"]] + except Exception as e: + logger.exception(f"Error in function parsing and lookup: {e}") + + try: + func(*command["args"], **command["kwargs"]) + except Exception as e: + logger.exception(f"Error executing {command_s}: {e}") def pybass_init(): diff --git a/gui/control_main.py b/gui/control_main.py index bb2ea0a3..03390db8 100644 --- a/gui/control_main.py +++ b/gui/control_main.py @@ -1,10 +1,12 @@ import _thread import functools +import json import logging import math import os import sys import time +from typing import Dict, List, Optional import cv2 import numpy as np @@ -17,7 +19,7 @@ from qtpy import QtCore, QtGui, QtWidgets from qtpy.QtCore import QModelIndex, QRectF, Qt, QTimer from qtpy.QtGui import QIntValidator -from qtpy.QtWidgets import QCheckBox, QFrame, QGraphicsPixmapItem, QApplication +from qtpy.QtWidgets import QApplication, QCheckBox, QFrame, QGraphicsPixmapItem import albulaUtils import daq_utils @@ -26,9 +28,9 @@ from config_params import ( CRYOSTREAM_ONLINE, HUTCH_TIMER_DELAY, - SERVER_CHECK_DELAY, RASTER_GUI_XREC_FILL_DELAY, SAMPLE_TIMER_DELAY, + SERVER_CHECK_DELAY, VALID_DET_DIST, VALID_EXP_TIMES, VALID_TOTAL_EXP_TIMES, @@ -51,10 +53,11 @@ ) from gui.raster import RasterCell, RasterGroup from QPeriodicTable import QPeriodicTable -from threads import RaddoseThread, VideoThread, ServerCheckThread +from threads import RaddoseThread, ServerCheckThread, VideoThread logger = logging.getLogger() + def get_request_object_escan( reqObj, symbol, @@ -230,7 +233,7 @@ def __init__(self): ] self.mountedPin_pv.put(mountedPin) self.rasterExploreDialog = RasterExploreDialog() - + self.detDistMotorEntry.getEntry().setText( self.detDistRBVLabel.getEntry().text() ) # this is to fix the current val being overwritten by reso @@ -240,7 +243,7 @@ def __init__(self): self.changeControlMasterCB(1) self.controlMasterCheckBox.setChecked(True) self.XRFInfoDict = self.parseXRFTable() # I don't like this - #self.dewarTree.refreshTreeDewarView() + # self.dewarTree.refreshTreeDewarView() def setGuiValues(self, values): for item, value in values.items(): @@ -404,7 +407,7 @@ def createSampleTab(self): self.osc_end_ledit.textChanged[str].connect( functools.partial(self.totalExpChanged, "oscEnd") ) - if daq_utils.beamline == "fmx": + if daq_utils.beamline == "fmx": self.osc_end_ledit.textChanged.connect(self.calcLifetimeCB) hBoxColParams1.addWidget(colStartLabel) hBoxColParams1.addWidget(self.osc_start_ledit) @@ -1407,8 +1410,7 @@ def createSampleTab(self): lambda frame: self.updateCam(self.pixmap_item_HutchTop, frame) ) self.hutchTopCamThread.start() - serverCheckThread = ServerCheckThread( - parent=self, delay=SERVER_CHECK_DELAY) + serverCheckThread = ServerCheckThread(parent=self, delay=SERVER_CHECK_DELAY) serverCheckThread.visit_dir_changed.connect(QApplication.instance().quit) serverCheckThread.start() @@ -1425,9 +1427,7 @@ def annealButtonCB(self): try: ftime = float(self.annealTime_ledit.text()) if ftime >= 0.1 and ftime <= 5.0: - comm_s = "anneal(" + str(ftime) + ")" - logger.info(comm_s) - self.send_to_server(comm_s) + self.send_to_server("anneal", [ftime]) else: self.popupServerMessage( "Anneal time must be between 0.1 and 5.0 seconds." @@ -1703,18 +1703,12 @@ def saveVidSnapshotCB( if rasterHeatJpeg == None: if reqID != None: filePrefix = db_lib.getRequestByID(reqID)["request_obj"]["file_prefix"] - imagePath = ( - f"{getBlConfig('visitDirectory')}/snapshots/{filePrefix}{int(now)}.jpg" - ) + imagePath = f"{getBlConfig('visitDirectory')}/snapshots/{filePrefix}{int(now)}.jpg" else: if self.dataPathGB.prefix_ledit.text() != "": - imagePath = ( - f"{getBlConfig('visitDirectory')}/snapshots/{self.dataPathGB.prefix_ledit.text()}{int(now)}.jpg" - ) + imagePath = f"{getBlConfig('visitDirectory')}/snapshots/{self.dataPathGB.prefix_ledit.text()}{int(now)}.jpg" else: - imagePath = ( - f"{getBlConfig('visitDirectory')}/snapshots/capture{int(now)}.jpg" - ) + imagePath = f"{getBlConfig('visitDirectory')}/snapshots/capture{int(now)}.jpg" else: imagePath = rasterHeatJpeg logger.info("saving " + imagePath) @@ -2503,9 +2497,7 @@ def protoRadioToggledCB(self, text): pass def beamsizeComboActivatedCB(self, text): - comm_s = 'set_beamsize("' + str(text[0:2]) + '","' + str(text[2:4]) + '")' - logger.info(comm_s) - self.send_to_server(comm_s) + self.send_to_server("set_beamsize", [text[0:2], text[2:4]]) def protoComboActivatedCB(self, text): self.showProtParams() @@ -2610,10 +2602,7 @@ def popImportDialogCB(self): ) self.timerSample.start(SAMPLE_TIMER_DELAY) if fname != "": - logger.info(fname) - comm_s = f'importSpreadsheet("{fname[0]}", "{daq_utils.owner}")' - logger.info(comm_s) - self.send_to_server(comm_s) + self.send_to_server("importSpreadsheet", [fname[0], daq_utils.owner]) def setUserModeCB(self): self.vidActionDefineCenterRadio.setEnabled(False) @@ -2696,13 +2685,10 @@ def dewarViewToggleCheckCB(self): self.dewarTree.refreshTreePriorityView() def moveOmegaCB(self): - comm_s = ( - 'mvaDescriptor("omega",' - + str(self.sampleOmegaMoveLedit.getEntry().text()) - + ")" + self.send_to_server( + "mvaDescriptor", + ["omega", float(self.sampleOmegaMoveLedit.getEntry().text())], ) - logger.info(comm_s) - self.send_to_server(comm_s) def moveEnergyCB(self): energyRequest = float(str(self.energy_ledit.text())) @@ -2710,9 +2696,7 @@ def moveEnergyCB(self): self.popupServerMessage("Energy change must be less than 10 ev") return else: - comm_s = 'mvaDescriptor("energy",' + str(self.energy_ledit.text()) + ")" - logger.info(comm_s) - self.send_to_server(comm_s) + self.send_to_server("mvaDescriptor", ["energy", float(self.energy_ledit.text())]) def setLifetimeCB(self, lifetime): if hasattr(self, "sampleLifetimeReadback_ledit"): @@ -2747,7 +2731,7 @@ def spawnRaddoseThread(self): vecLen = float(self.vecLenLabelOutput.text()) except: pass - + try: wedge = float(self.osc_end_ledit.text()) raddose_thread = RaddoseThread( @@ -2779,22 +2763,18 @@ def setTransCB(self): except ValueError as e: self.popupServerMessage("Please enter a valid number") return - comm_s = "setTrans(" + str(self.transmission_ledit.text()) + ")" - logger.info(comm_s) - self.send_to_server(comm_s) + self.send_to_server("setTrans", [float(self.transmission_ledit.text())]) def setDCStartCB(self): currentPos = float(self.sampleOmegaRBVLedit.getEntry().text()) % 360.0 self.setGuiValues({"osc_start": currentPos}) def moveDetDistCB(self): - comm_s = ( - 'mvaDescriptor("detectorDist",' - + str(self.detDistMotorEntry.getEntry().text()) - + ")" - ) - logger.info(comm_s) - self.send_to_server(comm_s) + self.send_to_server("mvaDescriptor", + [ + "detectorDist", + float(self.detDistMotorEntry.getEntry().text()), + ]) def omegaTweakNegCB(self): tv = float(self.omegaTweakVal_ledit.text()) @@ -2850,17 +2830,14 @@ def omegaTweakCB(self, tv): self.popupServerMessage("You don't have control") def autoCenterLoopCB(self): - logger.info("auto center loop") - self.send_to_server("loop_center_xrec()") + self.send_to_server("loop_center_xrec") def autoRasterLoopCB(self): self.selectedSampleID = self.selectedSampleRequest["sample"] - comm_s = "autoRasterLoop(" + str(self.selectedSampleID) + ")" - self.send_to_server(comm_s) + self.send_to_server("autoRasterLoop", [self.selectedSampleID]) def runRastersCB(self): - comm_s = "snakeRaster(" + str(self.selectedSampleRequest["uid"]) + ")" - self.send_to_server(comm_s) + self.send_to_server("snakeRaster", [self.selectedSampleRequest["uid"]]) def drawInteractiveRasterCB(self): # any polygon for now, interactive or from xrec for i in range(len(self.polyPointItems)): @@ -2936,7 +2913,7 @@ def center3LoopCB(self): logger.info("3-click center loop") self.threeClickCount = 1 self.click3Button.setStyleSheet("background-color: yellow") - self.send_to_server('mvaDescriptor("omega",0)') + self.send_to_server("mvaDescriptor", ["omega", 0]) def fillPolyRaster( self, rasterReq, waitTime=1 @@ -3113,7 +3090,7 @@ def takeRasterSnapshot(self, rasterReq): reqID=rasterReq["uid"], rasterHeatJpeg=jpegImageFilename, ) - self.send_to_server(f"ispybLib.insertRasterResult('{rasterReq['uid']}', '{visitName}')") + self.send_to_server("ispybLib.insertRasterResult", [str(rasterReq["uid"]), str(visitName)]) def reFillPolyRaster(self): rasterEvalOption = str(self.rasterEvalComboBox.currentText()) @@ -3212,10 +3189,10 @@ def selectAllCenterCB(self): self.centeringMarksList[i]["graphicsItem"].setSelected(True) def lightUpCB(self): - self.send_to_server("backlightBrighter()") + self.send_to_server("backlightBrighter") def lightDimCB(self): - self.send_to_server("backlightDimmer()") + self.send_to_server("backlightDimmer") def eraseRastersCB(self): if self.rasterList != []: @@ -3571,38 +3548,21 @@ def pixelSelect(self, event): True ) # because it's easy to forget defineCenter is on if self.zoom4Radio.isChecked(): - comm_s = ( - "changeImageCenterHighMag(" - + str(x_click) - + "," - + str(y_click) - + ",1)" + self.send_to_server( + "changeImageCenterHighMag", [x_click, y_click, 1] ) elif self.zoom3Radio.isChecked(): - comm_s = ( - "changeImageCenterHighMag(" - + str(x_click) - + "," - + str(y_click) - + ",0)" + self.send_to_server( + "changeImageCenterHighMag", [x_click, y_click, 0] ) if self.zoom2Radio.isChecked(): - comm_s = ( - "changeImageCenterLowMag(" - + str(x_click) - + "," - + str(y_click) - + ",1)" + self.send_to_server( + "changeImageCenterLowMag", [x_click, y_click, 1] ) elif self.zoom1Radio.isChecked(): - comm_s = ( - "changeImageCenterLowMag(" - + str(x_click) - + "," - + str(y_click) - + ",0)" + self.send_to_server( + "changeImageCenterLowMag", [x_click, y_click, 0] ) - self.send_to_server(comm_s) return if self.vidActionRasterDefRadio.isChecked(): self.click_positions.append(event.pos()) @@ -3630,11 +3590,29 @@ def pixelSelect(self, event): if self.threeClickCount > 0: # 3-click centering self.threeClickCount = self.threeClickCount + 1 - comm_s = f'center_on_click({correctedC2C_x},{correctedC2C_y},{fov["x"]},{fov["y"]},source="screen",jog=90,viewangle={current_viewangle})' + comm_s = ( + "center_on_click", + [ + correctedC2C_x, + correctedC2C_y, + fov["x"], + fov["y"], + {"source": "screen", "jog": 90, "viewangle": current_viewangle}, + ], + ) else: - comm_s = f'center_on_click({correctedC2C_x},{correctedC2C_y},{fov["x"]},{fov["y"]},source="screen",maglevel=0,viewangle={current_viewangle})' + comm_s = ( + "center_on_click", + [ + correctedC2C_x, + correctedC2C_y, + fov["x"], + fov["y"], + {"source": "screen", "maglevel": 0, "viewangle": current_viewangle}, + ], + ) if not self.vidActionRasterExploreRadio.isChecked(): - self.aux_send_to_server(comm_s) + self.aux_send_to_server(*comm_s) if self.threeClickCount == 4: self.threeClickCount = 0 self.click3Button.setStyleSheet("background-color: None") @@ -4193,19 +4171,24 @@ def collectQueueCB(self): if currentRequest == {}: self.addRequestsToAllSelectedCB() logger.info("running queue") - self.send_to_server("runDCQueue()") + self.send_to_server("runDCQueue") + def warmupGripperCB(self): - self.send_to_server("warmupGripper()") + self.send_to_server("warmupGripper") + def dryGripperCB(self): - self.send_to_server("dryGripper()") + self.send_to_server("dryGripper") + def enableTScreenGripperCB(self): - self.send_to_server("enableDewarTscreen()") + self.send_to_server("enableDewarTscreen") + def parkGripperCB(self): - self.send_to_server("parkGripper()") + self.send_to_server("parkGripper") + def restartServerCB(self): if self.controlEnabled(): @@ -4436,14 +4419,15 @@ def puckToDewarCB(self): def stopRunCB(self): logger.info("stopping collection") - self.aux_send_to_server("stopDCQueue(1)") + self.aux_send_to_server("stopDCQueue", [1]) def stopQueueCB(self): logger.info("stopping queue") if self.pauseQueueButton.text() == "Continue": - self.aux_send_to_server("continue_data_collection()") + self.aux_send_to_server("continue_data_collection") else: - self.aux_send_to_server("stopDCQueue(2)") + self.aux_send_to_server("stopDCQueue", [2]) + def mountSampleCB(self): if getBlConfig("mountEnabled") == 0: @@ -4458,7 +4442,8 @@ def mountSampleCB(self): else: # No sample ID found, do nothing logger.info("No sample selected, cannot mount") return - self.send_to_server('mountSample("' + str(self.selectedSampleID) + '")') + self.send_to_server("mountSample", [self.selectedSampleID]) + self.zoom2Radio.setChecked(True) self.zoomLevelToggledCB("Zoom2") self.protoComboBox.setCurrentIndex(self.protoComboBox.findText(str("standard"))) @@ -4466,7 +4451,8 @@ def mountSampleCB(self): def unmountSampleCB(self): logger.info("unmount sample") - self.send_to_server("unmountSample()") + self.send_to_server("unmountSample") + def refreshCollectionParams(self, selectedSampleRequest, validate_hdf5=True): reqObj = selectedSampleRequest["request_obj"] @@ -4581,14 +4567,15 @@ def refreshCollectionParams(self, selectedSampleRequest, validate_hdf5=True): ) > 5.0 ): - comm_s = ( - 'mvaDescriptor("omega",' - + str( - selectedSampleRequest["request_obj"]["rasterDef"]["omega"] - ) - + ")" + + self.send_to_server( + "mvaDescriptor", + [ + "omega", + selectedSampleRequest["request_obj"]["rasterDef"]["omega"], + ], ) - self.send_to_server(comm_s) + if str(reqObj["protocol"]) == "eScan": try: self.escan_steps_ledit.setText(str(reqObj["steps"])) @@ -5178,24 +5165,41 @@ def controlEnabled(self): and self.controlMasterCheckBox.isChecked() ) - def send_to_server(self, s): - if s == "lockControl": + def send_to_server(self, function_name: str, args: "Optional[List]" = None, kwargs: "Optional[Dict]" = None): + if function_name == "lockControl": self.controlMaster_pv.put(0 - self.processID) return - if s == "unlockControl": + if function_name == "unlockControl": self.controlMaster_pv.put(self.processID) return if self.controlEnabled(): time.sleep(0.01) - logger.info("send_to_server: %s" % s) - self.comm_pv.put(s) + message = self.generate_server_message(function_name, args, kwargs) + logger.info(f"send_to_server: {message}") + self.comm_pv.put(message) else: self.popupServerMessage("You don't have control") - def aux_send_to_server(self, s): + def generate_server_message( + self, function_name: str, args: "Optional[List]" = None, kwargs: "Optional[Dict]" = None + ) -> str: + if not args: + args = [] + if not kwargs: + kwargs = {} + return json.dumps( + { + "function": function_name, + "args": args, + "kwargs": kwargs, + } + ) + + def aux_send_to_server(self, function_name: str, args: "Optional[List]" = None, kwargs: "Optional[Dict]" = None): if self.controlEnabled(): time.sleep(0.01) - logger.info("aux_send_to_server: %s" % s) - self.immediate_comm_pv.put(s) + message = self.generate_server_message(function_name, args, kwargs) + logger.info(f"aux_send_to_server: {message}") + self.immediate_comm_pv.put(message) else: self.popupServerMessage("You don't have control") diff --git a/gui/dialog/screen_defaults.py b/gui/dialog/screen_defaults.py index a5f548c8..6a86e881 100644 --- a/gui/dialog/screen_defaults.py +++ b/gui/dialog/screen_defaults.py @@ -202,7 +202,7 @@ def reprocessRasterRequestCB(self): try: reqID = self.parent.selectedSampleRequest["uid"] self.parent.drawPolyRaster(db_lib.getRequestByID(reqID)) - self.parent.send_to_server('reprocessRaster("' + str(reqID) + '")') + self.parent.send_to_server("reprocessRaster", [reqID]) except: pass diff --git a/gui/dialog/staff_screen.py b/gui/dialog/staff_screen.py index 83f41023..13ce99d1 100644 --- a/gui/dialog/staff_screen.py +++ b/gui/dialog/staff_screen.py @@ -222,15 +222,13 @@ def getFastDPNodeList(self): return nodeList def setFastDPNodesCB(self): - comm_s = "fastDPNodes(" - for i in range(0, self.fastDPNodeCount): - comm_s = comm_s + str(self.fastDPNodeEntryList[i].text()) - if i == self.fastDPNodeCount - 1: - comm_s = comm_s + ")" - else: - comm_s = comm_s + "," - logger.info(comm_s) - self.parent.send_to_server(comm_s) + self.parent.send_to_server( + "fastDPNodes", + [ + int(self.fastDPNodeEntryList[i].text()) + for i in range(self.fastDPNodeCount) + ], + ) def lockGuiCB(self): self.parent.send_to_server("lockControl") @@ -239,54 +237,46 @@ def unLockGuiCB(self): self.parent.send_to_server("unlockControl") def setSpotNodesCB(self): - comm_s = "spotNodes(" - for i in range(0, self.spotNodeCount): - comm_s = comm_s + str(self.spotNodeEntryList[i].text()) - if i == self.spotNodeCount - 1: - comm_s = comm_s + ")" - else: - comm_s = comm_s + "," - logger.info(comm_s) - self.parent.send_to_server(comm_s) + self.parent.send_to_server( + "spotNodes", + [int(self.spotNodeEntryList[i].text()) for i in range(self.spotNodeCount)], + ) def unmountColdCB(self): - self.parent.send_to_server("unmountCold()") + self.parent.send_to_server("unmountCold") def openPort1CB(self): - self.parent.send_to_server("openPort(1)") + self.parent.send_to_server("openPort", [1]) def setBeamcenterCB(self): self.parent.send_to_server( - "set_beamcenter (" - + str(self.beamcenterX_ledit.text()) - + "," - + str(self.beamcenterY_ledit.text()) - + ")" + "set_beamcenter", + [self.beamcenterX_ledit.text(), self.beamcenterY_ledit.text()], ) def closePortsCB(self): - self.parent.send_to_server("closePorts()") + self.parent.send_to_server("closePorts") def clearMountedSampleCB(self): - self.parent.send_to_server("clearMountedSample()") + self.parent.send_to_server("clearMountedSample") def recoverRobotCB(self): - self.parent.aux_send_to_server("recoverRobot()") + self.parent.aux_send_to_server("recoverRobot") def rebootEMBL_CB(self): - self.parent.aux_send_to_server("rebootEMBL()") + self.parent.aux_send_to_server("rebootEMBL") def restartEMBL_CB(self): - self.parent.send_to_server("restartEMBL()") + self.parent.send_to_server("restartEMBL") def openGripper_CB(self): - self.parent.send_to_server("openGripper()") + self.parent.send_to_server("openGripper") def closeGripper_CB(self): - self.parent.send_to_server("closeGripper()") + self.parent.send_to_server("closeGripper") def homePinsCB(self): - self.parent.send_to_server("homePins()") + self.parent.send_to_server("homePins") def robotOnCheckCB(self, state): if state == QtCore.Qt.Checked: diff --git a/gui/dialog/user_screen.py b/gui/dialog/user_screen.py index e4c0ef20..7322efcc 100644 --- a/gui/dialog/user_screen.py +++ b/gui/dialog/user_screen.py @@ -197,24 +197,22 @@ def __init__(self, parent: "ControlMain"): self.setLayout(vBoxColParams1) def setSlit1XCB(self): - comm_s = "setSlit1X(" + str(self.slit1XMotor_ledit.text()) + ")" - self.parent.send_to_server(comm_s) + self.parent.send_to_server("setSlit1X", [self.slit1XMotor_ledit.text()]) def setSlit1YCB(self): - comm_s = "setSlit1Y(" + str(self.slit1YMotor_ledit.text()) + ")" - self.parent.send_to_server(comm_s) + self.parent.send_to_server("setSlit1Y", [self.slit1YMotor_ledit.text()]) def unmountColdCB(self): - self.parent.send_to_server("unmountCold()") + self.parent.send_to_server("unmountCold") def testRobotCB(self): - self.parent.send_to_server("testRobot()") + self.parent.send_to_server("testRobot") def recoverRobotCB(self): - self.parent.send_to_server("recoverRobot()") + self.parent.send_to_server("recoverRobot") def dryGripperCB(self): - self.parent.send_to_server("dryGripper()") + self.parent.send_to_server("dryGripper") def stopDetCB(self): logger.info("stopping detector") @@ -235,16 +233,16 @@ def rebootZebraIOC_CB(self): self.parent.rebootZebraIOC_pv.put(1) def SEgovCB(self): - self.parent.send_to_server("setGovRobot(gov_robot, 'SE')") + self.parent.send_to_server("setGovState", ["SE"]) def SAgovCB(self): - self.parent.send_to_server("setGovRobot(gov_robot, 'SA')") + self.parent.send_to_server("setGovState", ["SA"]) def DAgovCB(self): - self.parent.send_to_server("setGovRobot(gov_robot, 'DA')") + self.parent.send_to_server("setGovState", ["DA"]) def BLgovCB(self): - self.parent.send_to_server("setGovRobot(gov_robot, 'BL')") + self.parent.send_to_server("setGovState", ["BL"]) def userScreenOKCB(self): self.hide()