From 9ec1ba5777956d787910ebe3b0710aecd53ba208 Mon Sep 17 00:00:00 2001 From: mskinner5278 Date: Tue, 21 May 2024 16:26:27 -0400 Subject: [PATCH 1/7] Added serverside support for heartbeat --- daq_main_common.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/daq_main_common.py b/daq_main_common.py index d39d40d9..4931db51 100755 --- a/daq_main_common.py +++ b/daq_main_common.py @@ -1,3 +1,4 @@ +from random import random import string import sys import os @@ -93,11 +94,17 @@ def process_command_file(command_file_name): def process_immediate_commands(frequency): + memory_beat = beamline_support.pvGet("heartbeat_pv") while (1): if (len(immediate_command_list) > 0): command = immediate_command_list.pop(0) logger.info('immediate command: %s' % command) process_input(command) + if memory_beat == beamline_support.pvGet("heartbeat_pv"): + memory_beat = random.randint(0, 1000) + beamline_support.pvPut("heartbeat_pv", str(memory_beat)) + else: + print("Heartbeat mismatch, possibility of multipler servers running.") time.sleep(frequency) def process_commands(frequency): From 4301998c4c6f3ee693c894521d38c0bcd236f1e2 Mon Sep 17 00:00:00 2001 From: mskinner5278 Date: Tue, 21 May 2024 16:57:06 -0400 Subject: [PATCH 2/7] add GUI support for heartbeat PV loss --- gui/control_main.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/gui/control_main.py b/gui/control_main.py index 272b42f0..c71049c2 100644 --- a/gui/control_main.py +++ b/gui/control_main.py @@ -200,6 +200,9 @@ def __init__(self): self.beamSize_pv = PV(daq_utils.beamlineComm + "size_mode") self.energy_pv = PV(daq_utils.motor_dict["energy"] + ".RBV") + self.heartbeat_pv = PV("heartbeat_pv") + self.last_heartbeat = time.time() + self.heartbeat_pv.add_callback(self.heartbeatCB) self.rasterStepDefs = {"Coarse": 30.0, "Fine": 20.0, "VFine": 10.0} self.createSampleTab() @@ -1553,6 +1556,9 @@ def createSampleTab(self): serverCheckThread.visit_dir_changed.connect(QApplication.instance().quit) serverCheckThread.start() + self.heartbeat_thread = _thread.start_new_thread(self.monitorHeartbeat, ()) + self.heartbeat_thread.start() + def updateCam(self, pixmapItem: "QGraphicsPixmapItem", frame): pixmapItem.setPixmap(frame) @@ -1576,6 +1582,15 @@ def annealButtonCB(self): except: pass + def heartbeatCB(self): + self.last_heartbeat = time.time() + + def monitorHeartbeat(self): + while True: + time.sleep(1) + if time.time() - self.last_heartbeat > 10: + self.popupServerMessage("Server not responding") + def hideRastersCB(self, state): if state == QtCore.Qt.Checked: self.eraseRastersCB() From 7e4b167ddf184decc3c86d559f1bd25daf4d9d71 Mon Sep 17 00:00:00 2001 From: mskinner5278 Date: Wed, 22 May 2024 15:58:34 -0400 Subject: [PATCH 3/7] updated with heartbeat pv name --- daq_main_common.py | 8 ++++---- gui/control_main.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/daq_main_common.py b/daq_main_common.py index 4931db51..bac485f7 100755 --- a/daq_main_common.py +++ b/daq_main_common.py @@ -94,17 +94,17 @@ def process_command_file(command_file_name): def process_immediate_commands(frequency): - memory_beat = beamline_support.pvGet("heartbeat_pv") + memory_beat = beamline_support.pvGet('XF:19ID2-ES:NYX{Comm}server_heartbeat') while (1): if (len(immediate_command_list) > 0): command = immediate_command_list.pop(0) logger.info('immediate command: %s' % command) process_input(command) - if memory_beat == beamline_support.pvGet("heartbeat_pv"): + if memory_beat == beamline_support.pvGet('XF:19ID2-ES:NYX{Comm}server_heartbeat'): memory_beat = random.randint(0, 1000) - beamline_support.pvPut("heartbeat_pv", str(memory_beat)) + beamline_support.pvPut('XF:19ID2-ES:NYX{Comm}server_heartbeat', str(memory_beat)) else: - print("Heartbeat mismatch, possibility of multipler servers running.") + print('Heartbeat mismatch, possibility of multipler servers running.') time.sleep(frequency) def process_commands(frequency): diff --git a/gui/control_main.py b/gui/control_main.py index c71049c2..a5163da9 100644 --- a/gui/control_main.py +++ b/gui/control_main.py @@ -200,7 +200,7 @@ def __init__(self): self.beamSize_pv = PV(daq_utils.beamlineComm + "size_mode") self.energy_pv = PV(daq_utils.motor_dict["energy"] + ".RBV") - self.heartbeat_pv = PV("heartbeat_pv") + self.heartbeat_pv = PV("XF:19ID2-ES:NYX{Comm}server_heartbeat") self.last_heartbeat = time.time() self.heartbeat_pv.add_callback(self.heartbeatCB) self.rasterStepDefs = {"Coarse": 30.0, "Fine": 20.0, "VFine": 10.0} From e88e42490285ec2126ebd174f8d376f368b3e6b6 Mon Sep 17 00:00:00 2001 From: mskinner5278 Date: Thu, 23 May 2024 12:58:05 -0400 Subject: [PATCH 4/7] heartbeat pv converted to pyepics pv object --- daq_main_common.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/daq_main_common.py b/daq_main_common.py index bac485f7..ec4867a1 100755 --- a/daq_main_common.py +++ b/daq_main_common.py @@ -43,7 +43,8 @@ def pybass_init(): daq_lib.init_var_channels() if getBlConfig(config_params.DETECTOR_OBJECT_TYPE) != config_params.DETECTOR_OBJECT_TYPE_NO_INIT: det_lib.init_detector() - daq_lib.message_string_pv = beamline_support.pvCreate(daq_utils.beamlineComm + "message_string") + daq_lib.message_string_pv = beamline_support.pvCreate(daq_utils.beamlineComm + "message_string") + daq_lib.heartbeat = beamline_support.pvCreate('XF:19ID2-ES:NYX{Comm}server_heartbeat') daq_lib.gui_popup_message_string_pv = beamline_support.pvCreate(daq_utils.beamlineComm + "gui_popup_message_string") beamline_lib.read_db() logger.info("init mots") @@ -94,15 +95,15 @@ def process_command_file(command_file_name): def process_immediate_commands(frequency): - memory_beat = beamline_support.pvGet('XF:19ID2-ES:NYX{Comm}server_heartbeat') + memory_beat = beamline_support.pvGet(daq_lib.heartbeat) while (1): if (len(immediate_command_list) > 0): command = immediate_command_list.pop(0) logger.info('immediate command: %s' % command) process_input(command) - if memory_beat == beamline_support.pvGet('XF:19ID2-ES:NYX{Comm}server_heartbeat'): + if memory_beat == beamline_support.pvGet(daq_lib.heartbeat): memory_beat = random.randint(0, 1000) - beamline_support.pvPut('XF:19ID2-ES:NYX{Comm}server_heartbeat', str(memory_beat)) + beamline_support.pvPut(daq_lib.heartbeat, str(memory_beat)) else: print('Heartbeat mismatch, possibility of multipler servers running.') time.sleep(frequency) From a53868afc20e698315b9e6bd7cb8d165e6f6fa2e Mon Sep 17 00:00:00 2001 From: Michael Skinner Date: Thu, 23 May 2024 13:25:53 -0400 Subject: [PATCH 5/7] final implementation for heartbeat message --- daq_main_common.py | 12 ++++++------ gui/control_main.py | 14 ++++++++++---- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/daq_main_common.py b/daq_main_common.py index ec4867a1..71cc0bb6 100755 --- a/daq_main_common.py +++ b/daq_main_common.py @@ -1,4 +1,4 @@ -from random import random +import random import string import sys import os @@ -101,11 +101,11 @@ def process_immediate_commands(frequency): command = immediate_command_list.pop(0) logger.info('immediate command: %s' % command) process_input(command) - if memory_beat == beamline_support.pvGet(daq_lib.heartbeat): - memory_beat = random.randint(0, 1000) - beamline_support.pvPut(daq_lib.heartbeat, str(memory_beat)) - else: - print('Heartbeat mismatch, possibility of multipler servers running.') + if memory_beat == beamline_support.pvGet(daq_lib.heartbeat): + memory_beat = random.randint(0, 1000) + beamline_support.pvPut(daq_lib.heartbeat, str(memory_beat)) + else: + print('Heartbeat mismatch, possibility of multipler servers running.') time.sleep(frequency) def process_commands(frequency): diff --git a/gui/control_main.py b/gui/control_main.py index a5163da9..abfb25f9 100644 --- a/gui/control_main.py +++ b/gui/control_main.py @@ -202,7 +202,6 @@ def __init__(self): self.energy_pv = PV(daq_utils.motor_dict["energy"] + ".RBV") self.heartbeat_pv = PV("XF:19ID2-ES:NYX{Comm}server_heartbeat") self.last_heartbeat = time.time() - self.heartbeat_pv.add_callback(self.heartbeatCB) self.rasterStepDefs = {"Coarse": 30.0, "Fine": 20.0, "VFine": 10.0} self.createSampleTab() @@ -1557,7 +1556,6 @@ def createSampleTab(self): serverCheckThread.start() self.heartbeat_thread = _thread.start_new_thread(self.monitorHeartbeat, ()) - self.heartbeat_thread.start() def updateCam(self, pixmapItem: "QGraphicsPixmapItem", frame): pixmapItem.setPixmap(frame) @@ -1582,14 +1580,21 @@ def annealButtonCB(self): except: pass - def heartbeatCB(self): + def heartbeatCB(self, **kwargs): self.last_heartbeat = time.time() def monitorHeartbeat(self): + ''' + This monitors the frequency of changes to the heartbeat PV. + After 10 seconds of no changes, it reports the issue to the + user, and waits 30 more seconds to keep from spamming. + ''' while True: time.sleep(1) if time.time() - self.last_heartbeat > 10: - self.popupServerMessage("Server not responding") + self.popup_message_string_pv.put("Server not responding") + time.sleep(30) + #self.popupServerMessage("Server not responding") def hideRastersCB(self, state): if state == QtCore.Qt.Checked: @@ -5382,6 +5387,7 @@ def initCallbacks(self): self.beamSizeSignal.connect(self.processBeamSize) self.beamSize_pv.add_callback(self.beamSizeChangedCB) + self.heartbeat_pv.add_callback(self.heartbeatCB) self.treeChanged_pv = PV(daq_utils.beamlineComm + "live_q_change_flag") self.refreshTreeSignal.connect(self.dewarTree.refreshTree) self.treeChanged_pv.add_callback(self.treeChangedCB) From 1fb710a84c6430ff4f04a5838f338439248ad527 Mon Sep 17 00:00:00 2001 From: mskinner5278 Date: Thu, 23 May 2024 14:07:23 -0400 Subject: [PATCH 6/7] spelling error in server message Co-authored-by: Jun Aishima --- daq_main_common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daq_main_common.py b/daq_main_common.py index 71cc0bb6..4e1e0c05 100755 --- a/daq_main_common.py +++ b/daq_main_common.py @@ -105,7 +105,7 @@ def process_immediate_commands(frequency): memory_beat = random.randint(0, 1000) beamline_support.pvPut(daq_lib.heartbeat, str(memory_beat)) else: - print('Heartbeat mismatch, possibility of multipler servers running.') + print('Heartbeat mismatch, possibility of multiple servers running.') time.sleep(frequency) def process_commands(frequency): From d4adae873801c0726cacb0d29b44112fc15c1c71 Mon Sep 17 00:00:00 2001 From: mskinner5278 Date: Thu, 23 May 2024 14:18:05 -0400 Subject: [PATCH 7/7] refactored heartbeat pv name --- gui/control_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/control_main.py b/gui/control_main.py index abfb25f9..fa7843c4 100644 --- a/gui/control_main.py +++ b/gui/control_main.py @@ -200,7 +200,7 @@ def __init__(self): self.beamSize_pv = PV(daq_utils.beamlineComm + "size_mode") self.energy_pv = PV(daq_utils.motor_dict["energy"] + ".RBV") - self.heartbeat_pv = PV("XF:19ID2-ES:NYX{Comm}server_heartbeat") + self.heartbeat_pv = PV(daq_utils.beamlineComm + "server_heartbeat") self.last_heartbeat = time.time() self.rasterStepDefs = {"Coarse": 30.0, "Fine": 20.0, "VFine": 10.0} self.createSampleTab()