From ba5bfe7199168d9518d4033257e7fbe0ee637f0c Mon Sep 17 00:00:00 2001 From: chrin Date: Wed, 14 May 2025 11:35:42 +0200 Subject: [PATCH] v1.8.0 with alarm messages to skin display --- config/control/hush.json | 4 + config/control/hush_full.json | 177 ++++++++++++++--- config/g1/hush.json | 4 + config/g2/hush.json | 4 + config/g3/hush.json | 4 + config/o2/hush.json | 4 + config/pif/hush.json | 4 + hush.py | 2 + hush.sh | 2 +- hush_g1.sh | 2 +- hush_g2.sh | 2 +- hush_g3.sh | 2 +- hush_o2.sh | 2 +- hush_pif.sh | 2 +- src/gui.py | 345 ++++++++++++++++++++++------------ timediff.py | 42 +++++ 16 files changed, 448 insertions(+), 154 deletions(-) create mode 100644 timediff.py diff --git a/config/control/hush.json b/config/control/hush.json index 824325e..6610046 100755 --- a/config/control/hush.json +++ b/config/control/hush.json @@ -10,6 +10,10 @@ }, "Expert":{ + "alarmMinor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Minor Alarm:", + "value" : " 90"}}, + "alarmMajor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Major Alarm:", + "value" : "180"}}, "debug": {"flag" : 0, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 0}} }, diff --git a/config/control/hush_full.json b/config/control/hush_full.json index 0c823f4..61936d2 100755 --- a/config/control/hush_full.json +++ b/config/control/hush_full.json @@ -3,19 +3,125 @@ "hasFile": 0, "loadInitFile": 0, "hasDaq": 0, - "hasH5": 0, - "hasEpics": 0 + "hasH5" : 0, + "hasEpics" : 0 }, - "hdf": { - "destination" : "./" + "ElogBooks": { + + "Proscan": { + "url": "https://elog-gfa.psi.ch:443/Proscan", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/proscan/", + "Required": {"Eintrag": ["Problem", "Info", "Tuning", + "Betriebs-Wechsel", "Überbrückung", + "Pikett", "Status", "Meldung-AK3", + "Tips & Tricks", "Schicht-Übergabe", + "Schicht-Auftrag"]}, + "Optional" : {"Effekt": ["","Abruch","Verzögerung","keiner","anderer"], + "System":["","Beamprobe Commissioning","Beamprobe Radial", "Diagnostik & Stopper Strahlweg", + "Extraktionselemente", "Gasversorgunung", "HF", "Interlock System", "Ionenquelle", + "Kontrollsysteme", "Kryo und Magnet", "Külung", "Mag.Speisegeräte", + "PaSS Gantry 1", "PaSS Gantry 2","PaSS Gantry 3", "PaSS OPTIS 2", + "PaSS Kontrollraum", "PaSS Frei","Phase Slit","Phasensonde", + "PSYS", "Schältplane Accel", "Speisegeräte Accel", + "TrimRods", "Vakuum", "Zyklotron allgemein", "Strahlweg", "SU", + "Andere Ursache"] + } + }, + + + "Sandkasten": { + "url": "https://elog-gfa.psi.ch:443/Sandkasten", + "destination": "/afs/psi.ch/intranet/Controls/tmp/elog/ePic/sls/", + "Required" : {"Eintrag": ["Problem","Anregung"]}, + "Optional" : {"Status": ["","Offen", "Geschlossen"]} + } + }, + + "Elog":{ + "useELOGenv": 0, + "host": "elog-gfa.psi.ch", + "book": "Proscan", + "url": "https://elog-gfa.psi.ch/Proscan", + "destination": "/afs/psi.ch/intranet/Controls/tmp/bdbase/ePic/" + }, + "stdlog":{ + "destination": "/tmp/" + }, + "screenshot": { + "destination": "/tmp/" + }, + "url": { + "archiver" : "https://data-ui.psi.ch/preselect?c1=proscan-archive/" + }, + "Shift":{ + "type" :"PRO-HUSH:SHIFT-TYPE" + }, + "headerMagnetSector" : ["G1","SH","G2","O2","PIF","G3"], + "header" : ["COMET","BMA1","G1","SH","G2","O2","PIF","G3","MASTER"], + + "COMET":{ + "status": "MMAC3:STR:2", + "colorObj" : "Machine", + "color": "gray", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 gray)" + }, + + "MASTER":{ + "status": "XPROSCAN:STAB:2", + "colorObj" : "Pk", + "color": "#00b7eb", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #00b7eb)" + }, + + "BMA1":{ + "status" : "BMA1:STA:2", + "colorObj" : "Machine", + "color": "gray", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 gray)" + }, + + "BMD1":{ + "status" : "BMD1:STA:2", + "colorObj" : "Machine", + "color": "gray", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 gray)" + }, + "B1B2":{ + "status": "PRO-HUSH:SHIFT-TYPE", + "colorObj" : "Machine", + "color": "#9888b6", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #9888b6)", + "device" : ["QMA1", "QMA2", "QMA3", "QMA4", "QMA5"], + "attribute" : ["SOL:2", "IST:2", "PWR:2"], + "standby": [-9.155, 9.155, -6.867, -6.867, 6.867], + "ref" : [-91.464, 102.359, -97.096, -44.269, 37.113], + "pwrref" : [9.065, 5.142, 4.061, 0.867, 0.597], + "iocDevice" : ["QMA1", "QMA2", "QMA5"] }, "G1":{ + "alarm": "PG1-HUSH:ALARM", + "status": "BME1:STA:2", + "mastershipStatus": "XPROSCAN:GANTRY1:STATUS", + "colorObj" : "Beamline", + "color": "#9888b6", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #9888b6)", + "device" : ["QME1", "QME2", "AME1", "QME4", "QME5", + "AME2", "QME7", "QME8", "QME10", "QME11"], + "attribute" : ["SOL:2", "IST:2", "PWR"], "standby": [-6.867, 6.867, 9.155, 6.867, 6.867, 9.155, 6.867, -6.867, 6.867, -6.867], - "ref" : [-43.813, 43.177, 157.28, 20.017, 30.544, 157,79, 42.203, -42.467, 52.179, -77.032], + "ref" : [-43.813, 43.177, 157.28, 20.017, 30.544, 157.79, 42.203, -42.467, 52.179, -77.032], "pwrref" : [0.789, 0.764, 17.341, 0.164, 0.366, 17.482, 0.737, 0.736, 1.096, 2.464], "iocDevice" : ["AME1", "AME2", "QME10"] }, "SH":{ + "alarm": "PSH-HUSH:ALARM", + "status": "BMA1:STA:2", + "colorObj" : "Machine", + "color": "gray", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 gray)", + "device" : ["QMA6", "QMA7", "QMA8", "QMA9", "AMA2", "QMA10", "QMA11", + "QMA12", "QMA13", "AMA3"], + "attribute" : ["SOL:2", "IST:2", "PWR"], "standby": [-6.8, 6.8, 6.8, -6.8, 6.8, 6.8, -6.8, -6.8, 6.8, 0], "ref" : [-34.048, 26.68, 26.68, -34.05, 87.764, 37.424, -47.207, -38.156, @@ -25,15 +131,33 @@ "iocDevice" : ["QMA7", "AMA2", "QMA12"] }, "G2":{ + "alarm": "PG2-HUSH:ALARM", + "status": "BMB1:STA:2", + "mastershipStatus": "XPROSCAN:GANTRY2:STATUS", + "colorObj" : "Beamline", + "color": "#9888b6", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #9888b6)", + "device" : ["QMB1", "QMB2", "QMB3", "QMB4", "QMB5", "QMF1", "QMF2", + "QMF3", "QMF4", "QMF6", "QMF7", "AMF1", "AMF2", "AMF3"], + "attribute" : ["SOL:2", "IST:2", "PWR"], "standby" : [-6.867, 6.867, -6.867, 6.867, -6.867, -7.553, 7.553, -7.553, 7.553, 7.553, -7.553, 10.758, 10.758, 23.804], "ref": [-41.056, 36.548, -30.490, 52.433, -27.636, -37.412, 41.966, -37.296, 51.200, 53.657, -41.966, 109.543, 109.405, 251.492], "pwrref" : [0.699, 0.545, 0.389, 1.152, 0.323, 0.374, 0.467, 0.378, 0.700, 0.772, 0.464, 7.114, 7.112, 21.727], - "iocDevice" : ["QMB2", "QMB4", "AMF1"] + "iocDevice" : ["QMB2", "QMB4", "AMF1"] }, "O2":{ + "alarm": "PO2-HUSH:ALARM", + "status": "BMC1:STA:2", + "mastershipStatus": "XPROSCAN:OPTIS2:STATUS", + "colorObj" : "Beamline", + "color": "#9888b6", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #9888b6)", + "device" : ["QMC1", "QMC2", "QMC3", "QMC4", "AMC1", "QMC5", "QMC6", + "QMC7", "QMC8", "QMC9"], + "attribute" : ["SOL:2", "IST:2", "PWR"], "standby": [-6.867, 6.867, 6.867, -6.867, 9.155, 6.867, -6.867, 6.867, -6.867, 6.867], "ref" : [-40.85, 26.974, 26.974, -40.851, 45.988, 30.890, -29.542, 33.742, @@ -43,6 +167,15 @@ "iocDevice" : ["QMC2", "AMC1", "QMC7"] }, "PIF":{ + "alarm": "PPIF-HUSH:ALARM", + "status": "BMD1:STA:2", + "mastershipStatus": "XPROSCAN:PIF:STATUS", + "colorObj" : "ATHOS", + "color": "#2e5894", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #2e5894)", + "device" : ["QMD1", "QMD2", "QMD3", "QMD4", "AMD1","QMD5", "QMD6", "QMD7", + "QMD8", "QMD9"], + "attribute" : ["SOL:2", "IST:2", "PWR"], "standby": [-6.800, 6.800, 6.800, -6.800, 6.800, 6.800, -6.800, 6.800, -6.800, 6.800], "ref" : [-36.159, 34.434, 42.277, -43, 135, 61, -62, 37, @@ -52,27 +185,23 @@ "iocDevice" : ["QMD2", "AMD1", "QMD9"] }, "G3":{ + "alarm": "PG3-HUSH:ALARM", + "status": "BMD2:STA:2", + "mastershipStatus": "XPROSCAN:GANTRY3:STATUS", + "colorObj" : "Beamline", + "color": "#9888b6", + "qlingrad": "qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #ffffff, stop: 1 #9888b6)", + "device" : ["QMD10", "QMD11", "QMD12"], + "attribute" : ["SOL:2", "IST:2", "PWR"], "standby": [-6.800, 6.800, -6.800], "ref" : [-40.388, 68.393, -34.805], "pwrref" : [0.64, 1.8, 0.46], "iocDevice" : ["QMD10", "QMD11", "QMD12"] - }, - "Parameters":{ - - "drawLine" : {"flag" : 0, "data":{ "widget": "QHLine", "text" : "None", "value" : "None"}}, - "delayRamp" : {"flag" : 1, "data":{ "widget": "QDoubleSpinBox", "text" : "Ramp delay (s):", - "value" : 0.1, "min": 0.00, "max": 0.20, "step": 0.01, - "tooltip":"Wait time between sending set point to each magnet in 'Restore'/'Standby' "}}, - "drawLine2" : {"flag" : 0, "data":{ "widget": "QHLine", "text" : "None", "value" : "None"}} - }, - "Expert":{ - "debug": {"flag" : 0, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, - "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 0}} - }, - "IOC": { - "resultsTabTitle" : "IOC" - }, - "Master": "Controlroom", - "Reset": "HUSH!" + "hdf": { + "destination" : "/tmp" + }, + "hdfGroups": { + "General":["Created","Author","Application","Comment","Filepath","Process","UID","User"] + } } diff --git a/config/g1/hush.json b/config/g1/hush.json index 6ec5c0f..ce89202 100755 --- a/config/g1/hush.json +++ b/config/g1/hush.json @@ -10,6 +10,10 @@ }, "Expert":{ + "alarmMinor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Minor Alarm:", + "value" : " 90"}}, + "alarmMajor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Major Alarm:", + "value" : "180"}}, "debug": {"flag" : 0, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 0}} }, diff --git a/config/g2/hush.json b/config/g2/hush.json index acd8d0b..0c39ad0 100755 --- a/config/g2/hush.json +++ b/config/g2/hush.json @@ -10,6 +10,10 @@ }, "Expert":{ + "alarmMinor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Minor Alarm:", + "value" : " 90"}}, + "alarmMajor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Major Alarm:", + "value" : "180"}}, "debug": {"flag" : 0, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 0}} }, diff --git a/config/g3/hush.json b/config/g3/hush.json index c8db0d4..8642849 100755 --- a/config/g3/hush.json +++ b/config/g3/hush.json @@ -10,6 +10,10 @@ }, "Expert":{ + "alarmMinor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Minor Alarm:", + "value" : " 90"}}, + "alarmMajor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Major Alarm:", + "value" : "180"}}, "debug": {"flag" : 0, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 0}} }, diff --git a/config/o2/hush.json b/config/o2/hush.json index 1e0bc68..0498cf8 100755 --- a/config/o2/hush.json +++ b/config/o2/hush.json @@ -10,6 +10,10 @@ }, "Expert":{ + "alarmMinor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Minor Alarm:", + "value" : " 90"}}, + "alarmMajor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Major Alarm:", + "value" : "180"}}, "debug": {"flag" : 0, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 0}} }, diff --git a/config/pif/hush.json b/config/pif/hush.json index 973f731..b2df758 100755 --- a/config/pif/hush.json +++ b/config/pif/hush.json @@ -10,6 +10,10 @@ }, "Expert":{ + "alarmMinor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Minor Alarm:", + "value" : " 90"}}, + "alarmMajor": {"flag" : 1, "data":{"widget": "QLineEdit", "text" : "Minutes to Major Alarm:", + "value" : "180"}}, "debug": {"flag" : 0, "data":{ "widget": "None", "text" : "Debug", "value" : 0}}, "simulation": {"flag" : 1, "data":{ "widget": "None", "text" : "Dry run", "value" : 0}} }, diff --git a/hush.py b/hush.py index 46a3117..1ad576c 100644 --- a/hush.py +++ b/hush.py @@ -58,6 +58,8 @@ class StartMain(BaseWindow): self.setMinimumHeight(974) self.setMinimumWidth(1460) + + def prepare_elog_message(self): diff --git a/hush.sh b/hush.sh index 3f1ef45..80cade8 100755 --- a/hush.sh +++ b/hush.sh @@ -1,5 +1,5 @@ #!/bin/bash -cd /proscan/bd/applications/hush/hla/1.7.0 +cd /proscan/bd/applications/hush/hla/1.8.0 # For use if script is sourced rather than executed appNameDefault="hush.sh" diff --git a/hush_g1.sh b/hush_g1.sh index 691848d..2543cdb 100755 --- a/hush_g1.sh +++ b/hush_g1.sh @@ -1,5 +1,5 @@ #!/bin/bash -cd /proscan/bd/applications/hush/hla/1.7.0 +cd /proscan/bd/applications/hush/hla/1.8.0 # For use if script is sourced rather than executed appNameDefault="hush_g1.sh" diff --git a/hush_g2.sh b/hush_g2.sh index f4ab775..dc90e82 100755 --- a/hush_g2.sh +++ b/hush_g2.sh @@ -1,5 +1,5 @@ #!/bin/bash -cd /proscan/bd/applications/hush/hla/1.7.0 +cd /proscan/bd/applications/hush/hla/1.8.0 # For use if script is sourced rather than executed appNameDefault="hush_g2.sh" diff --git a/hush_g3.sh b/hush_g3.sh index 06c47f6..96a79fa 100755 --- a/hush_g3.sh +++ b/hush_g3.sh @@ -1,5 +1,5 @@ #!/bin/bash -cd /proscan/bd/applications/hush/hla/1.7.0 +cd /proscan/bd/applications/hush/hla/1.8.0 # For use if script is sourced rather than executed appNameDefault="hush_g3.sh" diff --git a/hush_o2.sh b/hush_o2.sh index b17bec1..4f31bb8 100755 --- a/hush_o2.sh +++ b/hush_o2.sh @@ -1,5 +1,5 @@ #!/bin/bash -cd /proscan/bd/applications/hush/hla/1.7.0 +cd /proscan/bd/applications/hush/hla/1.8.0 # For use if script is sourced rather than executed appNameDefault="hush_o2.sh" diff --git a/hush_pif.sh b/hush_pif.sh index 7a57cb0..3db7eed 100755 --- a/hush_pif.sh +++ b/hush_pif.sh @@ -1,5 +1,5 @@ #!/bin/bash -cd /proscan/bd/applications/hush/hla/1.7.0 +cd /proscan/bd/applications/hush/hla/1.8.0 # For use if script is sourced rather than executed appNameDefault="hush_pif.sh" diff --git a/src/gui.py b/src/gui.py index a814d77..90e7bdd 100644 --- a/src/gui.py +++ b/src/gui.py @@ -6,7 +6,7 @@ import os import random import threading import time -from datetime import timedelta +from datetime import datetime, timedelta from qtpy.QtGui import QColor, QPixmap from qtpy.QtCore import __version__ as QT_VERSION_STR @@ -36,6 +36,12 @@ print(elog_directory) class AppGui(QWidget): '''The GUI class ''' + def time_difference(self, time0): + tn = datetime.now() + time1 = datetime(tn.year, tn.month, tn.day, tn.hour, tn.minute, tn.second) + difference = time1 - time0 + return divmod(difference.total_seconds(), 60) + def __init__(self, parent): #super(AppGui, self).__init__() super().__init__() # Python 3 style for super() @@ -54,6 +60,7 @@ class AppGui(QWidget): self.gui_header = self.parent.gui_header self.assigned_master = self.gui_header.assigned_master + self.simple_simple = None self.simple_standby = None self.simple_awake = None self.simple_status = None @@ -70,22 +77,36 @@ class AppGui(QWidget): 'statusStyleSheet']['awake-text'] self.standby_text = self.settings.data[ 'statusStyleSheet']['standby-text'] + + alarm_minor_color = self.settings.data['StyleGuide']['fgAlarmMinor'] + alarm_minor_color_str = f'background-color: {alarm_minor_color};' + self.alarm_minor_sss = ('QLabel {color:#000000; font-weight: bold; ' + + alarm_minor_color_str + '}') + + alarm_major_color = self.settings.data['StyleGuide']['fgAlarmMajor'] + alarm_major_color_str = f'background-color: {alarm_major_color};' + self.alarm_major_sss = ('QLabel {color:#000000; font-weight: bold; ' + + alarm_major_color_str + '}') + self.alarm_text = ' Awake but inactive for ' + + + no_alarm_color = self.settings.data['StyleGuide']['fgAlarmNoAlarm'] + no_alarm_color_str = f'background-color: {no_alarm_color};' + self.no_alarm_sss = ('QLabel {color:#000000; font-weight: bold; ' + + no_alarm_color_str + '}') + self.font_gui = self.parent.gui_frame.font_gui self.input_parameters = self.parent.input_parameters self.input_labels = self.parent.input_labels self.expert_parameters = self.parent.expert_parameters - self.gui_frame.expert_parameters_group.setFixedWidth(260) - self.gui_frame.expert_parameters_group.setFixedHeight(130) - self.gui_frame.operator_parameters_group.setFixedWidth(260) - #if "Controlroom" in self.settings.data["Master"]: - # self.gui_frame.operator_parameters_group.setFixedHeight(160) - #else: + self.gui_frame.expert_parameters_group.setFixedWidth(260) #260 + self.gui_frame.expert_parameters_group.setFixedHeight(180) #130 + self.gui_frame.operator_parameters_group.setFixedWidth(260) self.gui_frame.operator_parameters_group.setFixedHeight(130) self.gui_frame.measurement_tab_wgt.setFixedWidth(440) - self.gui_frame.measurement_tab_wgt.setFixedHeight(200) - # self.gui_frame.operator_wgt.setFixedHeight(240) - # self.gui_frame.expert_wgt.setFixedHeight(240) + self.gui_frame.measurement_tab_wgt.setFixedHeight(240) #200 + self.lock = threading.Lock() self.timer = QTimer() @@ -95,7 +116,8 @@ class AppGui(QWidget): self.timer_blink.setSingleShot(True) self.timer_blink.count = 0 - + + self.sec_state_list = ["PG1-HUSH:STATE", "PSH-HUSH:STATE", "PG2-HUSH:STATE", "PO2-HUSH:STATE", "PPIF-HUSH:STATE", "PG3-HUSH:STATE"] @@ -107,17 +129,16 @@ class AppGui(QWidget): self.gui_frame.central_tab_widget.tabBar().setTabText(0, "Control") #self.gui_frame.central_tab_widget.tabBar().setTabText(1, "IOC") - + print("====================================") if "Controlroom" in self.assigned_master: - - + shift_type = CAQMenu(self, pv_name="PRO-HUSH:SHIFT-TYPE") self.gui_frame.operator_parameters_group.layout().insertWidget( 0, QLabel(" Shift Type:")) self.gui_frame.operator_parameters_group.layout().insertWidget( 1, shift_type) self.gui_frame.operator_parameters_group.setFixedHeight(150) - self.gui_frame.measurement_tab_wgt.setFixedHeight(220) + self.gui_frame.results_wgt.setFixedWidth(1400) self.gui_frame.results_wgt.setFixedHeight(860) @@ -126,6 +147,7 @@ class AppGui(QWidget): self.reset_ioc_sm(), 0, 0, 1, 1) + print("=====================================") sec_prefix_list = [ sub[0: sub.index("-")] for sub in self.sec_state_list] @@ -179,8 +201,8 @@ class AppGui(QWidget): sector] = self.get_standby_dict(sector) print(self.sector_designated_magnet_values_dict, flush=True) - print("====================================================================") - print("self.assigned_master is ", self.assigned_master) + + print("self.assigned_master is ", self.assigned_master, flush=True) pv_list = [] @@ -200,8 +222,18 @@ class AppGui(QWidget): #Keep SH self.simple_sector_list = self.settings.data["headerMagnetSector"][ 1:] if "Controlroom" in self.assigned_master else self.sector_list + + self.simple_t0 = [None] * len(self.simple_sector_list) + self.simple_tdiff = [None] * len(self.simple_sector_list) + + for i, sector in enumerate(self.simple_sector_list): + pvdata = self.cafe.getPVCache(self.settings.data[sector]['status']) + tz = pvdata.tsDate + self.simple_t0[i] = datetime(tz[0], tz[1], tz[2], tz[3], tz[4], tz[5]) + self.simple_tdiff[i] = self.time_difference(self.simple_t0[i]) + print('sector, time difference = ', sector, self.simple_tdiff[i]) + - self.pv_name_in_sector_list = [None] * len(self.sector_list) for i, sector in enumerate(self.sector_list): print(i, sector, flush=True) @@ -280,32 +312,18 @@ class AppGui(QWidget): status_wgt = self.group_sector_status() status_wgt.setFixedHeight(340) - #qf = QFrame() - #qf.setFixedHeight(15) - #self.gui_frame.measurement_layout.addWidget(qf, 2, 0, 1, 1) + #qf = QLabel('HELP') + #qf.setFixedHeight(25) + #self.gui_frame.measurement_layout.addWidget(qf, 1, 0, 1, 1) self.gui_frame.measurement_layout.addWidget( status_wgt, 1, 0, 4, 1, alignment=Qt.AlignTop) - #qf = QFrame() - #qf.setFixedHeight(1) - #self.gui_frame.measurement_layout.addWidget(qf, 5, 0, 1, 1) - - ''' - qf1 = QFrame() - qf1.setFixedWidth(1) - - self.gui_frame.measurement_layout.addWidget( - qf1, 5, 1, 1, 1, alignment=Qt.AlignTop) - - qf2 = QFrame() - qf2.setFixedWidth(1) - self.gui_frame.measurement_layout.addWidget( - qf2, 0, 7, 1, 1, alignment=Qt.AlignTop) - ''' self.gui_frame.measurement_layout.setRowStretch(6, 90) self.gui_frame.measurement_layout.setColumnStretch(10, 90) - + self.gui_frame.measurement_layout.setVerticalSpacing(10) + + if "Controlroom" in self.assigned_master: self.gui_header.beam_current_wgt_dict[ "MASTER"].trigger_monitor_str.connect( @@ -322,14 +340,7 @@ class AppGui(QWidget): self.gui_frame.simulation_checkbox.stateChanged.connect( self.simulation_update) - ''' - for state in self.sec_state_list: - for sector in self.settings.data["headerMagnetSector"]: - if sector in state: - self.cafe.monitor(state, self.receive_sec_state) - break - ''' - + for key in self.sector_disruptor_dict: @@ -337,8 +348,8 @@ class AppGui(QWidget): print(key, flush=True) pvd = self.cafe.getPVCache( self.settings.data[key]["status"], dt="str") - pvd.show() - print(flush=True) + #pvd.show() + #print(flush=True) if "G1" in key: self.gui_header.beam_current_wgt_dict[ @@ -359,34 +370,15 @@ class AppGui(QWidget): self.gui_header.beam_current_wgt_dict[ key].trigger_monitor_str.connect(self.receive_g3_update) - ''' - if "G1" in key: - self.receive_g1_update( - pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity) - elif "SH" in key: - self.receive_sh_update( - pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity) - elif "G2" in key: - self.receive_g2_update( - pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity) - elif "O2" in key: - self.receive_o2_update( - pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity) - elif "PIF" in key: - self.receive_pif_update( - pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity) - elif "G3" in key: - self.receive_g3_update( - pvd.value[0], pvd.alarmStatus, pvd.alarmSeverity) - ''' + #Trigger group_submaster_wgt for wgt in self.submaster_wgt: - print("wgt.pv_name", wgt.pv_name, flush=True) + #print("wgt.pv_name", wgt.pv_name, flush=True) pvd = self.cafe.getPVCache(wgt.pv_name, dt='str') wgt.trigger_monitor_str.emit( pvd.value[0], pvd.status, pvd.alarmSeverity) - print("emit value =====================>", wgt.sector, pvd.value[0]) + #print("emit value =====================>", wgt.sector, pvd.value[0]) for sector in self.sector_list_all: if "B1B2" in sector: @@ -397,16 +389,70 @@ class AppGui(QWidget): for idx in gateway_indices: pv_name_gw = self.table_sol_dict[sector].pv_gateway[idx].pv_name pvd = self.cafe.getPVCache(pv_name_gw, dt='float') - print("pv_name_gw", pv_name_gw, flush=True) - pvd.show() + #print("pv_name_gw", pv_name_gw, flush=True) + #pvd.show() self.table_sol_dict[sector].pv_gateway[ idx].trigger_monitor_float.emit( pvd.value[0], pvd.status, pvd.alarmSeverity) - print("gw emit done") + #print("gw emit done") - - + self.timer_awake = QTimer() + self.timer_awake.timeout.connect(self.update_awake_alarm_message) + self.timer_awake.start(60000) + + + + def update_awake_alarm_message(self): + for sect in self.simple_sector_list: + idx = self.simple_sector_list.index(sect) + #print(" update_awake_alarm_message -------------- ", + # sect, self.sector_disruptor_dict[sect]) + if "Geschlossen" not in self.sector_disruptor_dict[sect]: + self.simple_alarm[idx].setStyleSheet(self.no_alarm_sss) + self.simple_alarm[idx].setText(' Active ') + + else: + pvdata = self.cafe.getPVCache(self.settings.data[sect]['status']) + tz = pvdata.tsDate + + self.simple_t0[idx] = datetime( + tz[0], tz[1], tz[2], tz[3], tz[4], tz[5]) + self.simple_tdiff[idx] = self.time_difference(self.simple_t0[idx]) + if self.simple_tdiff[idx][0] > int(self.input_parameters['alarmMajor']): + self.simple_alarm[idx].setStyleSheet(self.alarm_major_sss) + elif self.simple_tdiff[idx][0] > int(self.input_parameters['alarmMinor']): + self.simple_alarm[idx].setStyleSheet(self.alarm_minor_sss) + else: + self.simple_alarm[idx].setStyleSheet(self.no_alarm_sss) + + self.simple_alarm[idx].setText( + self.alarm_text + str(int(self.simple_tdiff[idx][0])) + ' min ') + + if 'Controlroom' in self.assigned_master: + if 'Geschlossen' not in self.sector_disruptor_dict['SH']: + + disruptor_list = [self.sector_disruptor_dict['G3'], + self.sector_disruptor_dict['PIF'], + self.sector_disruptor_dict['O2'], + self.sector_disruptor_dict['G2']] + + #must take on value *Geschlossen" + if disruptor_list[1:] == disruptor_list[:-1]: + + idx_start = self.simple_sector_list.index('G2') + idx_end = self.simple_sector_list.index('G3') + tdiff_list =[] + tmin = 2000 + idx_min = 0 + for i in range (idx_start, idx_end): + if self.simple_tdiff[i][0] < tmin: + idx_min = i + + idx = self.simple_sector_list.index('SH') + self.simple_tdiff[idx] = self.simple_tdiff[idx_min] + self.simple_alarm[idx].setText(self.alarm_text + str( + int(self.simple_tdiff[idx][0])) + ' min ') def enable_disable_beamline(self, sect, sector_line, value): def is_submaster(local_sector, local_sector_line): @@ -433,16 +479,24 @@ class AppGui(QWidget): #"Geschlossen" in self.submastership_dict[local_sector]) else: return self.gui_header.is_master() - - #print("sect/value/sector_line", sect, value, sector_line, flush=True) + + pvdata = self.cafe.getPVCache(self.settings.data[sect]['status']) + tz = pvdata.tsDate + idx = self.simple_sector_list.index(sect) + self.simple_t0[idx] = datetime(tz[0], tz[1], tz[2], tz[3], tz[4], tz[5]) + self.simple_tdiff[idx] = self.time_difference(self.simple_t0[idx]) + #print('sector, time difference ===========>>> ', + # sect, idx, self.simple_tdiff[idx]) + + + self.update_awake_alarm_message() + if not sector_line: return self.sector_disruptor_dict[sect] = value - print('sector_line', sector_line) - print('simple_sector_line', self.simple_sector_list) - + for sector in reversed(sector_line): idx = self.simple_sector_list.index(sector) @@ -495,43 +549,55 @@ class AppGui(QWidget): ''' @Slot(str, int, int) def receive_sh_update(self, value, status, alarm_severity): + print("receive_sh_update===>", value, flush=True) if status == self.cyca.ICAFE_CA_OP_CONN_DOWN: return self.enable_disable_beamline("SH", self.gui_header.sh_line, value) - + #print("receive_sh_update===>", value, flush=True) + #print(self.sector_disruptor_dict, flush=True) + #pvd = self.cafe.getPVCache(self.settings.data['SH']['status']) + #pvd.show() + @Slot(str, int, int) def receive_g1_update(self, value, status, alarm_severity): if status == self.cyca.ICAFE_CA_OP_CONN_DOWN: return self.enable_disable_beamline("G1", self.gui_header.g1_line, value) - + + @Slot(str, int, int) def receive_g3_update(self, value, status, alarm_severity): #print("receive_g3_update", self.sender(), flush=True) #print(dir(self.sender())) if status == self.cyca.ICAFE_CA_OP_CONN_DOWN: return - self.enable_disable_beamline("G3", self.gui_header.g3_line[self.idx:], value) - + self.enable_disable_beamline("G3", self.gui_header.g3_line[self.idx:], + value) + + @Slot(str, int, int) def receive_o2_update(self, value, status, alarm_severity): if status == self.cyca.ICAFE_CA_OP_CONN_DOWN: return - self.enable_disable_beamline("O2", self.gui_header.o2_line[self.idx:], value) - + self.enable_disable_beamline("O2", self.gui_header.o2_line[self.idx:], + value) + + @Slot(str, int, int) def receive_g2_update(self, value, status, alarm_severity): if status == self.cyca.ICAFE_CA_OP_CONN_DOWN: return - self.enable_disable_beamline("G2", self.gui_header.g2_line[self.idx:], value) - + self.enable_disable_beamline("G2", self.gui_header.g2_line[self.idx:], + value) + + @Slot(str, int, int) def receive_pif_update(self, value, status, alarm_severity): if status == self.cyca.ICAFE_CA_OP_CONN_DOWN: return self.enable_disable_beamline( "PIF", self.gui_header.pif_line[self.idx:], value) - + @Slot(str, int, int) def receive_b1b2_update(self, value, status, alarm_severity): if status == self.cyca.ICAFE_CA_OP_CONN_DOWN: @@ -667,12 +733,12 @@ class AppGui(QWidget): self.check_status_list(_pymodule, "getScalarListCache", pv_list, status_list, _line()) # check standby values - in_standby = True + in_standby = False for value, standby in zip(value_list, standby_value_list): #if abs(value) < abs(standby) * 0.8 or abs(value) > abs( # standby) * 1.2: - if abs(value) > abs(standby) * 1.2: - in_standby = False + if abs(value) < abs(standby) * 1.2: + in_standby = True break return in_standby @@ -1124,21 +1190,24 @@ class AppGui(QWidget): idx = self.simple_sector_list.index(sector) text_color = self.settings.data[sector]["color"] text_color_str = f'color: {text_color};' - def paint_awake(): + + def paint_awake(): sss = ('QGroupBox {background-color:#ffe87c; font-weight: bold; ' + text_color_str + '}') self.simple_groupbox[idx].setStyleSheet(sss) self.simple_status[idx].setStyleSheet( 'QLabel{color:black; font-weight: bold;}') - self.simple_groupbox[idx].setStyleSheet(sss) #self.groupbox_awake_sss) + self.simple_groupbox[idx].setStyleSheet(sss) self.simple_status[idx].setText('Status: AWAKE') self.status_dict[sector].setStyleSheet(self.label_awake_sss) - self.status_dict[sector].setText(self.awake_text) #self.settings.data['statusStyleSheet']['awake-text']) + self.status_dict[sector].setText(self.awake_text) + + self.simple_alarm[idx].setVisible(True) + - def paint_asleep(): - + def paint_asleep(): sss = ('QGroupBox {background-color:#546bab; font-weight: bold; ' + text_color_str + '}') self.simple_groupbox[idx].setStyleSheet(sss) @@ -1146,24 +1215,28 @@ class AppGui(QWidget): self.simple_status[idx].setStyleSheet( 'QLabel{color:white; font-weight: bold;}') - self.simple_groupbox[idx].setStyleSheet(sss) #self.groupbox_standby_sss) + self.simple_groupbox[idx].setStyleSheet(sss) self.simple_status[idx].setText('Status: STANDBY') self.status_dict[sector].setStyleSheet(self.label_standby_sss) - self.status_dict[sector].setText(self.standby_text) #self.settings.data['statusStyleSheet']['standby-text']) - - if value and pv_name: + self.status_dict[sector].setText(self.standby_text) + self.simple_alarm[idx].setVisible(False) + + if value is not None and pv_name is not None: self.sector_designated_magnet_values_dict[sector][pv_name] = value #print(self.sector_designated_magnet_values_dict[sector], flush=True) - is_standby = True + is_standby = False for pv in self.sector_designated_magnet_values_dict[sector]: val_now = self.sector_designated_magnet_values_dict[sector][pv] val_standby = self.sector_designated_magnet_standby_dict[sector][pv] - - if abs(val_now) > (1.2 * abs(val_standby)): - is_standby = False - break; + + if abs(val_now) < (1.2 * abs(val_standby)): + is_standby = True + break; + + with self.lock: + #print("is standby", is_standby) if not is_standby: if not self.table_sol_dict[ sector].init_value_button.isEnabled(): @@ -1176,6 +1249,7 @@ class AppGui(QWidget): sector].init_value_button.setEnabled(True) if self.simple_awake: paint_awake() + #print("is standby false so paint awake ", is_standby) else: if self.table_sol_dict[sector].init_value_button.isEnabled(): @@ -1186,6 +1260,7 @@ class AppGui(QWidget): False) if self.simple_standby: paint_asleep() + #print("is standby true so paint standby ", is_standby) return is_standby @@ -1199,12 +1274,12 @@ class AppGui(QWidget): sender = self.sender() sector = sender.sector pv_name = sender.pv_name - #print("local_cb", sender.pv_name, value, status, - #alarm_severity, flush=True) + #print("designated_magnet_cb==========>", sender.pv_name, value, status, + # alarm_severity, flush=True) #self.sector_designated_magnet_values_dict[sector][pv_name] = value self.timer.singleShot(0, lambda: self.is_sector_standby( sector, pv_name, value)) - #print("designated_magnet_cb end for sector", sector, flush=True) + #print("designated_magnet_cb end for sector=========>", sector, flush=True) @@ -1755,7 +1830,9 @@ class AppGui(QWidget): self.simple_standby = [None] * len(self.simple_sector_list) self.simple_awake = [None] * len(self.simple_sector_list) self.simple_groupbox = [None] * len(self.simple_sector_list) + self.simple_alarm = [None] * len(self.simple_sector_list) + qgrido = QGridLayout() qwo = QGroupBox('Skin View') @@ -1765,10 +1842,22 @@ class AppGui(QWidget): icolumn = 0 for i, sector in enumerate(self.simple_sector_list): - + + self.simple_alarm[i] = QLabel('') + size_policy = self.simple_alarm[i].sizePolicy() + size_policy.setRetainSizeWhenHidden(True) + self.simple_alarm[i].setSizePolicy(size_policy) + self.simple_alarm[i].setFixedHeight(28) + self.simple_alarm[i].setFixedWidth(220) + self.simple_alarm[i].setAlignment(Qt.AlignCenter) + #text_color = self.settings.data['StyleGuide']['fgAlarmMinor'] + #text_color_str = f'background-color: {text_color};' + #sss = ('QLabel {color:#000000; font-weight: bold; ' + + # text_color_str + '}') + #self.simple_alarm[i].setStyleSheet(sss) self.simple_status[i] = QLabel(' Status: ') pv = 'P' + sector + '-HUSH:TOTPWR' - print('pv=', pv, flush=True) + #print('pv=', pv, flush=True) power = CAQLabel(self, pv, show_units=True, notify_freq_hz=1) self.simple_standby[i] = QPushButton(' Standby ') @@ -1792,6 +1881,7 @@ class AppGui(QWidget): qgrid.addWidget(power, 0, 1, 1, 1, Qt.AlignLeft) qgrid.addWidget(self.simple_standby[i], 1, 0, 1, 1, Qt.AlignCenter) qgrid.addWidget(self.simple_awake[i], 1, 1, 1, 1, Qt.AlignCenter) + qgrid.addWidget(self.simple_alarm[i], 2, 0, 1, 2, Qt.AlignCenter) qgrid.setContentsMargins(5, 20, 5, 0) @@ -1806,7 +1896,7 @@ class AppGui(QWidget): self.simple_groupbox[i].setLayout(qgrid) self.simple_groupbox[i].setFixedWidth(270) #280 - self.simple_groupbox[i].setFixedHeight(140) #140 + self.simple_groupbox[i].setFixedHeight(160) #140 irow = 0 if i < (hlength) else 1 @@ -1814,9 +1904,13 @@ class AppGui(QWidget): qgrido.addWidget(self.simple_groupbox[i], irow, icolumn, 1, 1, Qt.AlignCenter) - message = "Request Mastership to " - message += "go to Experiment Mode" if \ - "Controlroom" not in self.assigned_master else "ramp magnets" + #message = "Request Mastership to " + #message += "go to Experiment Mode" if \ + # "Controlroom" not in self.assigned_master else "ramp magnets" + if "Controlroom" in self.assigned_master: + message = "" + else: + message = "Request Mastership to go to Experiment Mode" ql = QLabel(message) ql.setStyleSheet('QLabel {color:black;}') @@ -1859,7 +1953,7 @@ class AppGui(QWidget): endpt = 0 if standby else 1 ramping = 'Ramping down \u21D3' if standby else 'Ramping up \u21D1' self.simple_status[idx].setText(ramping) - end = 14 #must be even no + end = 30 #must be even no for i in range(0, end): if i%2 == endpt: @@ -1868,8 +1962,8 @@ class AppGui(QWidget): self.simple_status[idx].setStyleSheet( 'QLabel{color:black; font-weight: bold;}') else: - sss = ('QGroupBox {background-color:#546bab;; font-weight: bold; ' + - text_color_str + '}') + sss = ('QGroupBox {background-color:#546bab;' + + 'font-weight: bold; ' + text_color_str + '}') self.simple_status[idx].setStyleSheet( 'QLabel{color:white; font-weight: bold;}') @@ -1892,10 +1986,13 @@ class AppGui(QWidget): #if not ready: self.simple_standby[idx].setEnabled(standby_enabled) self.simple_awake[idx].setEnabled(awake_enabled) - - pv = self.settings.data[sector]['device'][0] + "-SOL:2.PROC" - stat = self.cafe.set(pv, 1) - self.check_status(_pymodule, "set", pv, stat, _line()) - - QApplication.processEvents() + #pv = self.settings.data[sector]['device'][0] + "-SOL:2.PROC" + + print("blinking .. designated magnet list", + self.get_standby_list(sector), flush=True) + for pv in self.get_standby_list(sector): + pv_proc = pv + ".PROC" + stat = self.cafe.set(pv_proc, 1) + self.check_status(_pymodule, "set", pv_proc, stat, _line()) + QApplication.processEvents() diff --git a/timediff.py b/timediff.py new file mode 100644 index 0000000..3cca486 --- /dev/null +++ b/timediff.py @@ -0,0 +1,42 @@ +from datetime import datetime +import time +import PyCafe +cafe = PyCafe.CyCafe() +pd=cafe.getPV("BMA1:STA:2") +tz = pd.tsDate +time0 = datetime(tz[0], tz[1], tz[2], tz[3], tz[4], tz[5]) +tn = datetime.now() + +time1 = datetime(tn.year, tn.month, tn.day, tn.hour, tn.minute, tn.second) + +difference = time1 - time0 + +minutes = divmod(difference.total_seconds(), 60) +print('Total difference in minutes: ', int(minutes[0]), 'minutes', int(minutes[1]), 'seconds') + + +def time_difference(): + tn = datetime.now() + time1 = datetime(tn.year, tn.month, tn.day, tn.hour, tn.minute, tn.second) + difference = time1 - time0 + return divmod(difference.total_seconds(), 60) + + + +def cb(handle, pv, pvdata): + global time0 + print(pv, handle) + pvdata.show() + tz = pvdata.tsDate + time0 = datetime(tz[0], tz[1], tz[2], tz[3], tz[4], tz[5]) + print("time0 in callback", time0) + +cafe.openMonitorPrepare() +cafe.monitorStart("BMA1:STA:2", cb=cb) +cafe.openMonitorNowAndWait(1.0) + +for i in range(0, 360): + time.sleep(1) + minutes = time_difference() + print('Total difference in minutes: ', int(minutes[0]), 'minutes', int(minutes[1]), 'seconds') + print("time0 actual", time0)