cgse 2024.7.0__py3-none-any.whl → 2025.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- README.md +27 -0
- bump.py +85 -0
- cgse-2025.0.1.dist-info/METADATA +38 -0
- cgse-2025.0.1.dist-info/RECORD +5 -0
- {cgse-2024.7.0.dist-info → cgse-2025.0.1.dist-info}/WHEEL +1 -2
- cgse-2024.7.0.dist-info/COPYING +0 -674
- cgse-2024.7.0.dist-info/COPYING.LESSER +0 -165
- cgse-2024.7.0.dist-info/METADATA +0 -144
- cgse-2024.7.0.dist-info/RECORD +0 -660
- cgse-2024.7.0.dist-info/entry_points.txt +0 -75
- cgse-2024.7.0.dist-info/top_level.txt +0 -2
- egse/__init__.py +0 -12
- egse/__main__.py +0 -32
- egse/aeu/aeu.py +0 -5238
- egse/aeu/aeu_awg.yaml +0 -265
- egse/aeu/aeu_crio.yaml +0 -273
- egse/aeu/aeu_cs.py +0 -627
- egse/aeu/aeu_devif.py +0 -321
- egse/aeu/aeu_main_ui.py +0 -903
- egse/aeu/aeu_metrics.py +0 -131
- egse/aeu/aeu_protocol.py +0 -463
- egse/aeu/aeu_psu.yaml +0 -204
- egse/aeu/aeu_ui.py +0 -873
- egse/aeu/arbdata/FccdRead.arb +0 -2
- egse/aeu/arbdata/FccdRead_min_points.arb +0 -2
- egse/aeu/arbdata/HeaterSync_FccdRead.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead25.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead31_25.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead37_50.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead43_75.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead50.arb +0 -2
- egse/aeu/arbdata/Heater_FccdRead_min_points.arb +0 -2
- egse/aeu/arbdata/ccdRead25.arb +0 -2
- egse/aeu/arbdata/ccdRead25_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead31_25.arb +0 -2
- egse/aeu/arbdata/ccdRead31_25_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead37_50.arb +0 -2
- egse/aeu/arbdata/ccdRead37_50_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead43_75.arb +0 -2
- egse/aeu/arbdata/ccdRead43_75_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead50.arb +0 -2
- egse/aeu/arbdata/ccdRead50_150ms.arb +0 -2
- egse/alert/__init__.py +0 -1049
- egse/alert/alertman.yaml +0 -37
- egse/alert/alertman_cs.py +0 -233
- egse/alert/alertman_ui.py +0 -600
- egse/alert/gsm/beaglebone.py +0 -138
- egse/alert/gsm/beaglebone.yaml +0 -51
- egse/alert/gsm/beaglebone_cs.py +0 -108
- egse/alert/gsm/beaglebone_devif.py +0 -122
- egse/alert/gsm/beaglebone_protocol.py +0 -46
- egse/bits.py +0 -318
- egse/camera.py +0 -44
- egse/collimator/__init__.py +0 -0
- egse/collimator/fcul/__init__.py +0 -0
- egse/collimator/fcul/ogse.py +0 -1077
- egse/collimator/fcul/ogse.yaml +0 -14
- egse/collimator/fcul/ogse_cs.py +0 -154
- egse/collimator/fcul/ogse_devif.py +0 -358
- egse/collimator/fcul/ogse_protocol.py +0 -132
- egse/collimator/fcul/ogse_sim.py +0 -431
- egse/collimator/fcul/ogse_ui.py +0 -1108
- egse/command.py +0 -699
- egse/config.py +0 -410
- egse/confman/__init__.py +0 -1058
- egse/confman/confman.yaml +0 -70
- egse/confman/confman_cs.py +0 -240
- egse/confman/confman_ui.py +0 -381
- egse/confman/setup_ui.py +0 -565
- egse/control.py +0 -632
- egse/coordinates/__init__.py +0 -534
- egse/coordinates/avoidance.py +0 -100
- egse/coordinates/cslmodel.py +0 -127
- egse/coordinates/laser_tracker_to_dict.py +0 -122
- egse/coordinates/point.py +0 -707
- egse/coordinates/pyplot.py +0 -194
- egse/coordinates/referenceFrame.py +0 -1279
- egse/coordinates/refmodel.py +0 -737
- egse/coordinates/rotationMatrix.py +0 -85
- egse/coordinates/transform3d_addon.py +0 -419
- egse/csl/__init__.py +0 -50
- egse/csl/commanding.py +0 -78
- egse/csl/icons/hexapod-connected-selected.svg +0 -30
- egse/csl/icons/hexapod-connected.svg +0 -30
- egse/csl/icons/hexapod-homing-selected.svg +0 -68
- egse/csl/icons/hexapod-homing.svg +0 -68
- egse/csl/icons/hexapod-retract-selected.svg +0 -56
- egse/csl/icons/hexapod-retract.svg +0 -51
- egse/csl/icons/hexapod-zero-selected.svg +0 -56
- egse/csl/icons/hexapod-zero.svg +0 -56
- egse/csl/icons/logo-puna.svg +0 -92
- egse/csl/icons/stop.svg +0 -1
- egse/csl/initialisation.py +0 -102
- egse/csl/mech_pos_settings.yaml +0 -18
- egse/das.py +0 -1240
- egse/das.yaml +0 -7
- egse/data/conf/SETUP_CSL_00000_170620_150000.yaml +0 -5
- egse/data/conf/SETUP_CSL_00001_170620_151010.yaml +0 -69
- egse/data/conf/SETUP_CSL_00002_170620_151020.yaml +0 -69
- egse/data/conf/SETUP_CSL_00003_170620_151030.yaml +0 -69
- egse/data/conf/SETUP_CSL_00004_170620_151040.yaml +0 -69
- egse/data/conf/SETUP_CSL_00005_170620_151050.yaml +0 -69
- egse/data/conf/SETUP_CSL_00006_170620_151060.yaml +0 -69
- egse/data/conf/SETUP_CSL_00007_170620_151070.yaml +0 -69
- egse/data/conf/SETUP_CSL_00008_170620_151080.yaml +0 -75
- egse/data/conf/SETUP_CSL_00010_210308_083016.yaml +0 -138
- egse/data/conf/SETUP_INTA_00000_170620_150000.yaml +0 -4
- egse/data/conf/SETUP_SRON_00000_170620_150000.yaml +0 -4
- egse/decorators.py +0 -514
- egse/device.py +0 -269
- egse/dpu/__init__.py +0 -2698
- egse/dpu/ccd_ui.py +0 -514
- egse/dpu/dpu.py +0 -783
- egse/dpu/dpu.yaml +0 -153
- egse/dpu/dpu_cs.py +0 -272
- egse/dpu/dpu_ui.py +0 -671
- egse/dpu/fitsgen.py +0 -2096
- egse/dpu/fitsgen_ui.py +0 -399
- egse/dpu/hdf5_model.py +0 -332
- egse/dpu/hdf5_ui.py +0 -277
- egse/dpu/hdf5_viewer.py +0 -506
- egse/dpu/hk_ui.py +0 -468
- egse/dpu_commands.py +0 -81
- egse/dsi/__init__.py +0 -33
- egse/dsi/_libesl.py +0 -232
- egse/dsi/constants.py +0 -296
- egse/dsi/esl.py +0 -630
- egse/dsi/rmap.py +0 -444
- egse/dsi/rmapci.py +0 -39
- egse/dsi/spw.py +0 -335
- egse/dsi/spw_state.py +0 -29
- egse/dummy.py +0 -318
- egse/dyndummy.py +0 -179
- egse/env.py +0 -278
- egse/exceptions.py +0 -88
- egse/fdir/__init__.py +0 -26
- egse/fdir/fdir_manager.py +0 -85
- egse/fdir/fdir_manager.yaml +0 -37
- egse/fdir/fdir_manager_controller.py +0 -136
- egse/fdir/fdir_manager_cs.py +0 -164
- egse/fdir/fdir_manager_interface.py +0 -15
- egse/fdir/fdir_remote.py +0 -73
- egse/fdir/fdir_remote.yaml +0 -30
- egse/fdir/fdir_remote_controller.py +0 -30
- egse/fdir/fdir_remote_cs.py +0 -94
- egse/fdir/fdir_remote_interface.py +0 -9
- egse/fdir/fdir_remote_popup.py +0 -26
- egse/fee/__init__.py +0 -106
- egse/fee/f_fee_register.yaml +0 -43
- egse/fee/feesim.py +0 -914
- egse/fee/n_fee_hk.py +0 -768
- egse/fee/nfee.py +0 -188
- egse/filterwheel/__init__.py +0 -4
- egse/filterwheel/eksma/__init__.py +0 -49
- egse/filterwheel/eksma/fw8smc4.py +0 -657
- egse/filterwheel/eksma/fw8smc4.yaml +0 -121
- egse/filterwheel/eksma/fw8smc4_cs.py +0 -144
- egse/filterwheel/eksma/fw8smc4_devif.py +0 -473
- egse/filterwheel/eksma/fw8smc4_protocol.py +0 -82
- egse/filterwheel/eksma/fw8smc4_ui.py +0 -940
- egse/filterwheel/eksma/fw8smc5.py +0 -115
- egse/filterwheel/eksma/fw8smc5.yaml +0 -105
- egse/filterwheel/eksma/fw8smc5_controller.py +0 -307
- egse/filterwheel/eksma/fw8smc5_cs.py +0 -141
- egse/filterwheel/eksma/fw8smc5_interface.py +0 -65
- egse/filterwheel/eksma/fw8smc5_simulator.py +0 -29
- egse/filterwheel/eksma/fw8smc5_ui.py +0 -1065
- egse/filterwheel/eksma/testpythonfw.py +0 -215
- egse/fov/__init__.py +0 -65
- egse/fov/fov_hk.py +0 -710
- egse/fov/fov_ui.py +0 -859
- egse/fov/fov_ui_controller.py +0 -140
- egse/fov/fov_ui_model.py +0 -200
- egse/fov/fov_ui_view.py +0 -345
- egse/gimbal/__init__.py +0 -32
- egse/gimbal/symetrie/__init__.py +0 -26
- egse/gimbal/symetrie/alpha.py +0 -586
- egse/gimbal/symetrie/generic_gimbal_ui.py +0 -1521
- egse/gimbal/symetrie/gimbal.py +0 -877
- egse/gimbal/symetrie/gimbal.yaml +0 -168
- egse/gimbal/symetrie/gimbal_cs.py +0 -183
- egse/gimbal/symetrie/gimbal_protocol.py +0 -138
- egse/gimbal/symetrie/gimbal_ui.py +0 -361
- egse/gimbal/symetrie/pmac.py +0 -1006
- egse/gimbal/symetrie/pmac_regex.py +0 -83
- egse/graph.py +0 -132
- egse/gui/__init__.py +0 -47
- egse/gui/buttons.py +0 -378
- egse/gui/focalplane.py +0 -1285
- egse/gui/formatter.py +0 -10
- egse/gui/led.py +0 -162
- egse/gui/limitswitch.py +0 -143
- egse/gui/mechanisms.py +0 -587
- egse/gui/states.py +0 -148
- egse/gui/stripchart.py +0 -729
- egse/gui/styles.qss +0 -48
- egse/gui/switch.py +0 -112
- egse/h5.py +0 -274
- egse/help/__init__.py +0 -0
- egse/help/help_ui.py +0 -126
- egse/hexapod/__init__.py +0 -32
- egse/hexapod/symetrie/__init__.py +0 -137
- egse/hexapod/symetrie/alpha.py +0 -874
- egse/hexapod/symetrie/dynalpha.py +0 -1387
- egse/hexapod/symetrie/hexapod_ui.py +0 -1516
- egse/hexapod/symetrie/pmac.py +0 -1010
- egse/hexapod/symetrie/pmac_regex.py +0 -83
- egse/hexapod/symetrie/puna.py +0 -1167
- egse/hexapod/symetrie/puna.yaml +0 -193
- egse/hexapod/symetrie/puna_cs.py +0 -195
- egse/hexapod/symetrie/puna_protocol.py +0 -134
- egse/hexapod/symetrie/puna_ui.py +0 -433
- egse/hexapod/symetrie/punaplus.py +0 -107
- egse/hexapod/symetrie/zonda.py +0 -872
- egse/hexapod/symetrie/zonda.yaml +0 -337
- egse/hexapod/symetrie/zonda_cs.py +0 -172
- egse/hexapod/symetrie/zonda_devif.py +0 -414
- egse/hexapod/symetrie/zonda_protocol.py +0 -123
- egse/hexapod/symetrie/zonda_ui.py +0 -449
- egse/hk.py +0 -791
- egse/icons/aeu-cs-start.svg +0 -117
- egse/icons/aeu-cs-stop.svg +0 -118
- egse/icons/aeu-cs.svg +0 -107
- egse/icons/aeu_cs-started.svg +0 -112
- egse/icons/aeu_cs-stopped.svg +0 -112
- egse/icons/aeu_cs.svg +0 -55
- egse/icons/alert.svg +0 -1
- egse/icons/arrow-double-left.png +0 -0
- egse/icons/arrow-double-right.png +0 -0
- egse/icons/arrow-up.svg +0 -11
- egse/icons/backward.svg +0 -1
- egse/icons/busy.svg +0 -1
- egse/icons/cleaning.svg +0 -115
- egse/icons/color-scheme.svg +0 -1
- egse/icons/cs-connected-alert.svg +0 -91
- egse/icons/cs-connected-disabled.svg +0 -43
- egse/icons/cs-connected.svg +0 -89
- egse/icons/cs-not-connected.svg +0 -44
- egse/icons/double-left-arrow.svg +0 -1
- egse/icons/double-right-arrow.svg +0 -1
- egse/icons/erase-disabled.svg +0 -19
- egse/icons/erase.svg +0 -59
- egse/icons/fitsgen-start.svg +0 -47
- egse/icons/fitsgen-stop.svg +0 -48
- egse/icons/fitsgen.svg +0 -1
- egse/icons/forward.svg +0 -1
- egse/icons/fov-hk-start.svg +0 -33
- egse/icons/fov-hk-stop.svg +0 -37
- egse/icons/fov-hk.svg +0 -1
- egse/icons/front-desk.svg +0 -1
- egse/icons/home-actioned.svg +0 -15
- egse/icons/home-disabled.svg +0 -15
- egse/icons/home.svg +0 -13
- egse/icons/info.svg +0 -1
- egse/icons/invalid.png +0 -0
- egse/icons/led-green.svg +0 -20
- egse/icons/led-grey.svg +0 -20
- egse/icons/led-orange.svg +0 -20
- egse/icons/led-red.svg +0 -20
- egse/icons/led-square-green.svg +0 -134
- egse/icons/led-square-grey.svg +0 -134
- egse/icons/led-square-orange.svg +0 -134
- egse/icons/led-square-red.svg +0 -134
- egse/icons/limit-switch-all-green.svg +0 -115
- egse/icons/limit-switch-all-red.svg +0 -117
- egse/icons/limit-switch-el+.svg +0 -116
- egse/icons/limit-switch-el-.svg +0 -117
- egse/icons/location-marker.svg +0 -1
- egse/icons/logo-dpu.svg +0 -48
- egse/icons/logo-gimbal.svg +0 -112
- egse/icons/logo-huber.svg +0 -23
- egse/icons/logo-ogse.svg +0 -31
- egse/icons/logo-puna.svg +0 -92
- egse/icons/logo-tcs.svg +0 -29
- egse/icons/logo-zonda.svg +0 -66
- egse/icons/maximize.svg +0 -1
- egse/icons/meter.svg +0 -1
- egse/icons/more.svg +0 -45
- egse/icons/n-fee-hk-start.svg +0 -24
- egse/icons/n-fee-hk-stop.svg +0 -25
- egse/icons/n-fee-hk.svg +0 -83
- egse/icons/observing-off.svg +0 -46
- egse/icons/observing-on.svg +0 -46
- egse/icons/open-document-hdf5.png +0 -0
- egse/icons/open-document-hdf5.svg +0 -21
- egse/icons/ops-mode.svg +0 -1
- egse/icons/play-green.svg +0 -17
- egse/icons/plugged-disabled.svg +0 -27
- egse/icons/plugged.svg +0 -21
- egse/icons/pm_ui.svg +0 -1
- egse/icons/power-button-green.svg +0 -27
- egse/icons/power-button-red.svg +0 -27
- egse/icons/power-button.svg +0 -27
- egse/icons/radar.svg +0 -1
- egse/icons/radioactive.svg +0 -2
- egse/icons/reload.svg +0 -1
- egse/icons/remote-control-off.svg +0 -28
- egse/icons/remote-control-on.svg +0 -28
- egse/icons/repeat-blue.svg +0 -15
- egse/icons/repeat.svg +0 -1
- egse/icons/settings.svg +0 -1
- egse/icons/shrink.svg +0 -1
- egse/icons/shutter.svg +0 -1
- egse/icons/sign-off.svg +0 -1
- egse/icons/sign-on.svg +0 -1
- egse/icons/sim-mode.svg +0 -1
- egse/icons/small-buttons-go.svg +0 -20
- egse/icons/small-buttons-minus.svg +0 -51
- egse/icons/small-buttons-plus.svg +0 -51
- egse/icons/sponge.svg +0 -220
- egse/icons/start-button-disabled.svg +0 -84
- egse/icons/start-button.svg +0 -50
- egse/icons/stop-button-disabled.svg +0 -84
- egse/icons/stop-button.svg +0 -50
- egse/icons/stop-red.svg +0 -17
- egse/icons/stop.svg +0 -1
- egse/icons/switch-disabled-square.svg +0 -87
- egse/icons/switch-disabled.svg +0 -15
- egse/icons/switch-off-square.svg +0 -87
- egse/icons/switch-off.svg +0 -72
- egse/icons/switch-on-square.svg +0 -87
- egse/icons/switch-on.svg +0 -61
- egse/icons/temperature-control.svg +0 -44
- egse/icons/th_ui_logo.svg +0 -1
- egse/icons/unplugged.svg +0 -23
- egse/icons/unvalid.png +0 -0
- egse/icons/user-interface.svg +0 -1
- egse/icons/vacuum.svg +0 -1
- egse/icons/valid.png +0 -0
- egse/icons/zoom-to-pixel-dark.svg +0 -64
- egse/icons/zoom-to-pixel-white.svg +0 -36
- egse/images/big-rotation-stage.png +0 -0
- egse/images/connected-100.png +0 -0
- egse/images/cross.svg +0 -6
- egse/images/disconnected-100.png +0 -0
- egse/images/gui-icon.png +0 -0
- egse/images/home.svg +0 -6
- egse/images/info-icon.png +0 -0
- egse/images/led-black.svg +0 -89
- egse/images/led-green.svg +0 -85
- egse/images/led-orange.svg +0 -85
- egse/images/led-red.svg +0 -85
- egse/images/load-icon.png +0 -0
- egse/images/load-setup.png +0 -0
- egse/images/load.png +0 -0
- egse/images/pause.png +0 -0
- egse/images/play-button.svg +0 -8
- egse/images/play.png +0 -0
- egse/images/process-status.png +0 -0
- egse/images/restart.png +0 -0
- egse/images/search.png +0 -0
- egse/images/sma.png +0 -0
- egse/images/start.png +0 -0
- egse/images/stop-button.svg +0 -8
- egse/images/stop.png +0 -0
- egse/images/switch-off.svg +0 -48
- egse/images/switch-on.svg +0 -48
- egse/images/undo.png +0 -0
- egse/images/update-button.svg +0 -11
- egse/imageviewer/exposureselection.py +0 -475
- egse/imageviewer/imageviewer.py +0 -198
- egse/imageviewer/matchfocalplane.py +0 -179
- egse/imageviewer/subfieldposition.py +0 -133
- egse/lampcontrol/__init__.py +0 -4
- egse/lampcontrol/beaglebone/beaglebone.py +0 -178
- egse/lampcontrol/beaglebone/beaglebone.yaml +0 -62
- egse/lampcontrol/beaglebone/beaglebone_cs.py +0 -106
- egse/lampcontrol/beaglebone/beaglebone_devif.py +0 -150
- egse/lampcontrol/beaglebone/beaglebone_protocol.py +0 -73
- egse/lampcontrol/energetiq/__init__.py +0 -22
- egse/lampcontrol/energetiq/eq99.yaml +0 -98
- egse/lampcontrol/energetiq/lampEQ99.py +0 -283
- egse/lampcontrol/energetiq/lampEQ99_cs.py +0 -128
- egse/lampcontrol/energetiq/lampEQ99_devif.py +0 -158
- egse/lampcontrol/energetiq/lampEQ99_encode_decode_errors.py +0 -73
- egse/lampcontrol/energetiq/lampEQ99_protocol.py +0 -71
- egse/lampcontrol/energetiq/lampEQ99_ui.py +0 -465
- egse/lib/CentOS-7/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/CentOS-8/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/CentOS-8/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Debian/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Debian/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Debian/libetherspacelink_v35_21.dylib +0 -0
- egse/lib/Linux/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Linux/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Ubuntu-20/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Ubuntu-20/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/gssw/python3-gssw_2.2.3+31f63c9f-1_all.deb +0 -0
- egse/lib/ximc/__pycache__/pyximc.cpython-38 2.pyc +0 -0
- egse/lib/ximc/__pycache__/pyximc.cpython-38.pyc +0 -0
- egse/lib/ximc/libximc.framework/Frameworks/libbindy.dylib +0 -0
- egse/lib/ximc/libximc.framework/Frameworks/libxiwrapper.dylib +0 -0
- egse/lib/ximc/libximc.framework/Headers/ximc.h +0 -5510
- egse/lib/ximc/libximc.framework/Resources/Info.plist +0 -42
- egse/lib/ximc/libximc.framework/Resources/keyfile.sqlite +0 -0
- egse/lib/ximc/libximc.framework/libbindy.so +0 -0
- egse/lib/ximc/libximc.framework/libximc +0 -0
- egse/lib/ximc/libximc.framework/libximc.so +0 -0
- egse/lib/ximc/libximc.framework/libximc.so.7.0.0 +0 -0
- egse/lib/ximc/libximc.framework/libxiwrapper.so +0 -0
- egse/lib/ximc/pyximc.py +0 -922
- egse/listener.py +0 -179
- egse/logger/__init__.py +0 -243
- egse/logger/log_cs.py +0 -321
- egse/metrics.py +0 -102
- egse/mixin.py +0 -464
- egse/monitoring.py +0 -95
- egse/ni/alarms/__init__.py +0 -26
- egse/ni/alarms/cdaq9375.py +0 -300
- egse/ni/alarms/cdaq9375.yaml +0 -89
- egse/ni/alarms/cdaq9375_cs.py +0 -130
- egse/ni/alarms/cdaq9375_devif.py +0 -183
- egse/ni/alarms/cdaq9375_protocol.py +0 -48
- egse/obs_inspection.py +0 -165
- egse/observer.py +0 -41
- egse/obsid.py +0 -163
- egse/powermeter/__init__.py +0 -0
- egse/powermeter/ni/__init__.py +0 -38
- egse/powermeter/ni/cdaq9184.py +0 -224
- egse/powermeter/ni/cdaq9184.yaml +0 -73
- egse/powermeter/ni/cdaq9184_cs.py +0 -130
- egse/powermeter/ni/cdaq9184_devif.py +0 -201
- egse/powermeter/ni/cdaq9184_protocol.py +0 -48
- egse/powermeter/ni/cdaq9184_ui.py +0 -544
- egse/powermeter/thorlabs/__init__.py +0 -25
- egse/powermeter/thorlabs/pm100a.py +0 -380
- egse/powermeter/thorlabs/pm100a.yaml +0 -132
- egse/powermeter/thorlabs/pm100a_cs.py +0 -136
- egse/powermeter/thorlabs/pm100a_devif.py +0 -127
- egse/powermeter/thorlabs/pm100a_protocol.py +0 -80
- egse/powermeter/thorlabs/pm100a_ui.py +0 -725
- egse/process.py +0 -451
- egse/procman/__init__.py +0 -834
- egse/procman/cannot_start_process_popup.py +0 -43
- egse/procman/procman.yaml +0 -49
- egse/procman/procman_cs.py +0 -201
- egse/procman/procman_ui.py +0 -2081
- egse/protocol.py +0 -605
- egse/proxy.py +0 -531
- egse/randomwalk.py +0 -140
- egse/reg.py +0 -585
- egse/reload.py +0 -122
- egse/reprocess.py +0 -693
- egse/resource.py +0 -333
- egse/rmap.py +0 -406
- egse/rst.py +0 -135
- egse/search.py +0 -182
- egse/serialdevice.py +0 -190
- egse/services.py +0 -247
- egse/services.yaml +0 -68
- egse/settings.py +0 -379
- egse/settings.yaml +0 -980
- egse/setup.py +0 -1181
- egse/shutter/__init__.py +0 -0
- egse/shutter/thorlabs/__init__.py +0 -19
- egse/shutter/thorlabs/ksc101.py +0 -205
- egse/shutter/thorlabs/ksc101.yaml +0 -105
- egse/shutter/thorlabs/ksc101_cs.py +0 -136
- egse/shutter/thorlabs/ksc101_devif.py +0 -201
- egse/shutter/thorlabs/ksc101_protocol.py +0 -71
- egse/shutter/thorlabs/ksc101_ui.py +0 -548
- egse/shutter/thorlabs/sc10.py +0 -82
- egse/shutter/thorlabs/sc10.yaml +0 -52
- egse/shutter/thorlabs/sc10_controller.py +0 -81
- egse/shutter/thorlabs/sc10_cs.py +0 -108
- egse/shutter/thorlabs/sc10_interface.py +0 -25
- egse/shutter/thorlabs/sc10_simulator.py +0 -30
- egse/simulator.py +0 -41
- egse/slack.py +0 -61
- egse/socketdevice.py +0 -218
- egse/sockets.py +0 -218
- egse/spw.py +0 -1401
- egse/stages/__init__.py +0 -12
- egse/stages/aerotech/ensemble.py +0 -245
- egse/stages/aerotech/ensemble.yaml +0 -205
- egse/stages/aerotech/ensemble_controller.py +0 -275
- egse/stages/aerotech/ensemble_cs.py +0 -110
- egse/stages/aerotech/ensemble_interface.py +0 -132
- egse/stages/aerotech/ensemble_parameters.py +0 -433
- egse/stages/aerotech/ensemble_simulator.py +0 -27
- egse/stages/aerotech/mgse_sim.py +0 -188
- egse/stages/arun/smd3.py +0 -110
- egse/stages/arun/smd3.yaml +0 -68
- egse/stages/arun/smd3_controller.py +0 -470
- egse/stages/arun/smd3_cs.py +0 -112
- egse/stages/arun/smd3_interface.py +0 -53
- egse/stages/arun/smd3_simulator.py +0 -27
- egse/stages/arun/smd3_stop.py +0 -16
- egse/stages/huber/__init__.py +0 -49
- egse/stages/huber/smc9300.py +0 -920
- egse/stages/huber/smc9300.yaml +0 -63
- egse/stages/huber/smc9300_cs.py +0 -178
- egse/stages/huber/smc9300_devif.py +0 -345
- egse/stages/huber/smc9300_protocol.py +0 -113
- egse/stages/huber/smc9300_sim.py +0 -547
- egse/stages/huber/smc9300_ui.py +0 -973
- egse/state.py +0 -173
- egse/statemachine.py +0 -274
- egse/storage/__init__.py +0 -1067
- egse/storage/persistence.py +0 -2295
- egse/storage/storage.yaml +0 -79
- egse/storage/storage_cs.py +0 -231
- egse/styles/dark.qss +0 -343
- egse/styles/default.qss +0 -48
- egse/synoptics/__init__.py +0 -417
- egse/synoptics/syn.yaml +0 -9
- egse/synoptics/syn_cs.py +0 -195
- egse/system.py +0 -1611
- egse/tcs/__init__.py +0 -14
- egse/tcs/tcs.py +0 -879
- egse/tcs/tcs.yaml +0 -14
- egse/tcs/tcs_cs.py +0 -202
- egse/tcs/tcs_devif.py +0 -292
- egse/tcs/tcs_protocol.py +0 -180
- egse/tcs/tcs_sim.py +0 -177
- egse/tcs/tcs_ui.py +0 -543
- egse/tdms.py +0 -171
- egse/tempcontrol/__init__.py +0 -23
- egse/tempcontrol/agilent/agilent34970.py +0 -109
- egse/tempcontrol/agilent/agilent34970.yaml +0 -44
- egse/tempcontrol/agilent/agilent34970_cs.py +0 -114
- egse/tempcontrol/agilent/agilent34970_devif.py +0 -182
- egse/tempcontrol/agilent/agilent34970_protocol.py +0 -96
- egse/tempcontrol/agilent/agilent34972.py +0 -111
- egse/tempcontrol/agilent/agilent34972.yaml +0 -44
- egse/tempcontrol/agilent/agilent34972_cs.py +0 -115
- egse/tempcontrol/agilent/agilent34972_devif.py +0 -189
- egse/tempcontrol/agilent/agilent34972_protocol.py +0 -98
- egse/tempcontrol/beaglebone/beaglebone.py +0 -341
- egse/tempcontrol/beaglebone/beaglebone.yaml +0 -110
- egse/tempcontrol/beaglebone/beaglebone_cs.py +0 -117
- egse/tempcontrol/beaglebone/beaglebone_protocol.py +0 -134
- egse/tempcontrol/beaglebone/beaglebone_ui.py +0 -674
- egse/tempcontrol/digalox/digalox.py +0 -115
- egse/tempcontrol/digalox/digalox.yaml +0 -36
- egse/tempcontrol/digalox/digalox_cs.py +0 -108
- egse/tempcontrol/digalox/digalox_protocol.py +0 -56
- egse/tempcontrol/keithley/__init__.py +0 -33
- egse/tempcontrol/keithley/daq6510.py +0 -662
- egse/tempcontrol/keithley/daq6510.yaml +0 -105
- egse/tempcontrol/keithley/daq6510_cs.py +0 -163
- egse/tempcontrol/keithley/daq6510_devif.py +0 -343
- egse/tempcontrol/keithley/daq6510_protocol.py +0 -79
- egse/tempcontrol/keithley/daq6510_sim.py +0 -186
- egse/tempcontrol/lakeshore/__init__.py +0 -33
- egse/tempcontrol/lakeshore/lsci.py +0 -361
- egse/tempcontrol/lakeshore/lsci.yaml +0 -162
- egse/tempcontrol/lakeshore/lsci_cs.py +0 -174
- egse/tempcontrol/lakeshore/lsci_devif.py +0 -292
- egse/tempcontrol/lakeshore/lsci_protocol.py +0 -76
- egse/tempcontrol/lakeshore/lsci_ui.py +0 -387
- egse/tempcontrol/ni/__init__.py +0 -0
- egse/tempcontrol/spid/spid.py +0 -109
- egse/tempcontrol/spid/spid.yaml +0 -81
- egse/tempcontrol/spid/spid_controller.py +0 -279
- egse/tempcontrol/spid/spid_cs.py +0 -136
- egse/tempcontrol/spid/spid_protocol.py +0 -107
- egse/tempcontrol/spid/spid_ui.py +0 -723
- egse/tempcontrol/srs/__init__.py +0 -22
- egse/tempcontrol/srs/ptc10.py +0 -867
- egse/tempcontrol/srs/ptc10.yaml +0 -227
- egse/tempcontrol/srs/ptc10_cs.py +0 -128
- egse/tempcontrol/srs/ptc10_devif.py +0 -116
- egse/tempcontrol/srs/ptc10_protocol.py +0 -39
- egse/tempcontrol/srs/ptc10_ui.py +0 -906
- egse/ups/apc/apc.py +0 -236
- egse/ups/apc/apc.yaml +0 -45
- egse/ups/apc/apc_cs.py +0 -101
- egse/ups/apc/apc_protocol.py +0 -125
- egse/user.yaml +0 -7
- egse/vacuum/beaglebone/beaglebone.py +0 -149
- egse/vacuum/beaglebone/beaglebone.yaml +0 -44
- egse/vacuum/beaglebone/beaglebone_cs.py +0 -108
- egse/vacuum/beaglebone/beaglebone_devif.py +0 -159
- egse/vacuum/beaglebone/beaglebone_protocol.py +0 -192
- egse/vacuum/beaglebone/beaglebone_ui.py +0 -638
- egse/vacuum/instrutech/igm402.py +0 -91
- egse/vacuum/instrutech/igm402.yaml +0 -90
- egse/vacuum/instrutech/igm402_controller.py +0 -124
- egse/vacuum/instrutech/igm402_cs.py +0 -108
- egse/vacuum/instrutech/igm402_interface.py +0 -49
- egse/vacuum/instrutech/igm402_simulator.py +0 -36
- egse/vacuum/keller/kellerBus.py +0 -256
- egse/vacuum/keller/leo3.py +0 -100
- egse/vacuum/keller/leo3.yaml +0 -38
- egse/vacuum/keller/leo3_controller.py +0 -81
- egse/vacuum/keller/leo3_cs.py +0 -101
- egse/vacuum/keller/leo3_interface.py +0 -33
- egse/vacuum/mks/evision.py +0 -86
- egse/vacuum/mks/evision.yaml +0 -75
- egse/vacuum/mks/evision_cs.py +0 -101
- egse/vacuum/mks/evision_devif.py +0 -313
- egse/vacuum/mks/evision_interface.py +0 -60
- egse/vacuum/mks/evision_simulator.py +0 -24
- egse/vacuum/mks/evision_ui.py +0 -701
- egse/vacuum/pfeiffer/acp40.py +0 -87
- egse/vacuum/pfeiffer/acp40.yaml +0 -60
- egse/vacuum/pfeiffer/acp40_controller.py +0 -117
- egse/vacuum/pfeiffer/acp40_cs.py +0 -109
- egse/vacuum/pfeiffer/acp40_interface.py +0 -40
- egse/vacuum/pfeiffer/acp40_simulator.py +0 -37
- egse/vacuum/pfeiffer/tc400.py +0 -87
- egse/vacuum/pfeiffer/tc400.yaml +0 -83
- egse/vacuum/pfeiffer/tc400_controller.py +0 -136
- egse/vacuum/pfeiffer/tc400_cs.py +0 -109
- egse/vacuum/pfeiffer/tc400_interface.py +0 -70
- egse/vacuum/pfeiffer/tc400_simulator.py +0 -35
- egse/vacuum/pfeiffer/tpg261.py +0 -80
- egse/vacuum/pfeiffer/tpg261.yaml +0 -66
- egse/vacuum/pfeiffer/tpg261_controller.py +0 -150
- egse/vacuum/pfeiffer/tpg261_cs.py +0 -109
- egse/vacuum/pfeiffer/tpg261_interface.py +0 -59
- egse/vacuum/pfeiffer/tpg261_simulator.py +0 -23
- egse/version.py +0 -174
- egse/visitedpositions.py +0 -398
- egse/windowing.py +0 -213
- egse/zmq/__init__.py +0 -28
- egse/zmq/spw.py +0 -160
- egse/zmq_ser.py +0 -41
- scripts/alerts/cold.yaml +0 -278
- scripts/alerts/example_alerts.yaml +0 -54
- scripts/alerts/transition.yaml +0 -14
- scripts/alerts/warm.yaml +0 -49
- scripts/analyse_n_fee_hk_data.py +0 -52
- scripts/check_hdf5_files.py +0 -192
- scripts/check_register_sync.py +0 -47
- scripts/check_tcs_calib_coef.py +0 -90
- scripts/correct_ccd_cold_temperature_cal.py +0 -157
- scripts/create_hdf5_report.py +0 -293
- scripts/csl_model.py +0 -420
- scripts/csl_restore_setup.py +0 -229
- scripts/export-grafana-dashboards.py +0 -49
- scripts/fdir/cs_recovery/fdir_cs_recovery.py +0 -54
- scripts/fdir/fdir_table.yaml +0 -70
- scripts/fdir/fdir_test_recovery.py +0 -10
- scripts/fdir/hw_recovery/fdir_agilent_hw_recovery.py +0 -73
- scripts/fdir/limit_recovery/fdir_agilent_limit.py +0 -61
- scripts/fdir/limit_recovery/fdir_bb_heater_limit.py +0 -59
- scripts/fdir/limit_recovery/fdir_ensemble_limit.py +0 -33
- scripts/fdir/limit_recovery/fdir_pressure_limit_recovery.py +0 -71
- scripts/fix_csv.py +0 -80
- scripts/ias/correct_ccd_temp_cal_elfique.py +0 -43
- scripts/ias/correct_ccd_temp_cal_floreffe.py +0 -43
- scripts/ias/correct_trp_swap_achel.py +0 -199
- scripts/inta/correct_ccd_temp_cal_duvel.py +0 -43
- scripts/inta/correct_ccd_temp_cal_gueuze.py +0 -43
- scripts/n_fee_supply_voltage_calculation.py +0 -92
- scripts/playground.py +0 -30
- scripts/print_hdf5_hk_data.py +0 -68
- scripts/print_register_map.py +0 -43
- scripts/remove_lines_between_matches.py +0 -188
- scripts/sron/commanding/control_heaters.py +0 -44
- scripts/sron/commanding/pumpdown.py +0 -46
- scripts/sron/commanding/set_pid_setpoint.py +0 -19
- scripts/sron/commanding/shutdown_bbb_heaters.py +0 -10
- scripts/sron/commanding/shutdown_pumps.py +0 -33
- scripts/sron/correct_mgse_coordinates_brigand_chimay.py +0 -272
- scripts/sron/correct_trp_swap_brigand.py +0 -204
- scripts/sron/gimbal_conversions.py +0 -75
- scripts/sron/tm_gen/tm_gen_agilent.py +0 -37
- scripts/sron/tm_gen/tm_gen_heaters.py +0 -4
- scripts/sron/tm_gen/tm_gen_spid.py +0 -13
- scripts/update_operational_cgse.py +0 -268
- scripts/update_operational_cgse_old.py +0 -273
egse/procman/procman_ui.py
DELETED
|
@@ -1,2081 +0,0 @@
|
|
|
1
|
-
import importlib
|
|
2
|
-
import logging
|
|
3
|
-
import multiprocessing
|
|
4
|
-
import pickle
|
|
5
|
-
import threading
|
|
6
|
-
from enum import Enum
|
|
7
|
-
from pathlib import Path
|
|
8
|
-
|
|
9
|
-
import sys
|
|
10
|
-
import time
|
|
11
|
-
import zmq
|
|
12
|
-
from PyQt5.QtCore import QObject, QLockFile
|
|
13
|
-
from PyQt5.QtCore import QThread
|
|
14
|
-
from PyQt5.QtCore import Qt
|
|
15
|
-
from PyQt5.QtCore import pyqtSignal
|
|
16
|
-
from PyQt5.QtCore import pyqtSlot
|
|
17
|
-
from PyQt5.QtGui import QCloseEvent, QIcon
|
|
18
|
-
from PyQt5.QtWidgets import QApplication, QScrollArea, QAction, QWidget, QSizePolicy, QMessageBox
|
|
19
|
-
from PyQt5.QtWidgets import QFrame
|
|
20
|
-
from PyQt5.QtWidgets import QGridLayout
|
|
21
|
-
from PyQt5.QtWidgets import QGroupBox
|
|
22
|
-
from PyQt5.QtWidgets import QHBoxLayout
|
|
23
|
-
from PyQt5.QtWidgets import QLabel
|
|
24
|
-
from PyQt5.QtWidgets import QMainWindow
|
|
25
|
-
from PyQt5.QtWidgets import QVBoxLayout
|
|
26
|
-
from prometheus_client import start_http_server
|
|
27
|
-
|
|
28
|
-
from egse.confman import ConfigurationManagerProxy
|
|
29
|
-
from egse.confman import is_configuration_manager_active
|
|
30
|
-
from egse.control import is_control_server_active, Response, Failure
|
|
31
|
-
from egse.device import DeviceInterface
|
|
32
|
-
from egse.gui import show_info_message
|
|
33
|
-
from egse.gui.buttons import ToggleButton, TouchButton
|
|
34
|
-
from egse.gui.led import Indic
|
|
35
|
-
from egse.gui.led import LED
|
|
36
|
-
from egse.obsid import ObservationIdentifier
|
|
37
|
-
from egse.process import ProcessStatus
|
|
38
|
-
from egse.process import SubProcess
|
|
39
|
-
from egse.procman import ProcessManagerProxy
|
|
40
|
-
from egse.resource import get_resource
|
|
41
|
-
from egse.settings import Settings
|
|
42
|
-
from egse.setup import Setup
|
|
43
|
-
from egse.system import do_every
|
|
44
|
-
from egse.system import find_class
|
|
45
|
-
from egse.zmq_ser import connect_address
|
|
46
|
-
from egse.zmq_ser import set_address_port
|
|
47
|
-
|
|
48
|
-
logging.basicConfig(level=logging.INFO, format=Settings.LOG_FORMAT_FULL)
|
|
49
|
-
|
|
50
|
-
GUI_SETTINGS = Settings.load("PM GUI")
|
|
51
|
-
LOGGER = logging.getLogger(__name__)
|
|
52
|
-
SITE = Settings.load("SITE")
|
|
53
|
-
|
|
54
|
-
class FILE_GENERATION_PROCESS_NAMES(str, Enum):
|
|
55
|
-
|
|
56
|
-
FITSGEN = "FITS generation"
|
|
57
|
-
FOV_HK = "FOV HK"
|
|
58
|
-
N_FEE_HK = "N-FEE HK"
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class ConfigurationMonitoringWorker(QObject):
|
|
62
|
-
|
|
63
|
-
# The thread will send a signal with the monitoring information:
|
|
64
|
-
# - The obsid;
|
|
65
|
-
# - The setup that has been loaded by the configuration manager.
|
|
66
|
-
|
|
67
|
-
setup_changed_signal = pyqtSignal(dict)
|
|
68
|
-
obsid_changed_signal = pyqtSignal(object) # This allows ObservationIdentifier or None to be returned
|
|
69
|
-
|
|
70
|
-
def __init__(self):
|
|
71
|
-
|
|
72
|
-
""" Initialisation of a monitoring thread.
|
|
73
|
-
|
|
74
|
-
This monitoring thread will listen on the monitoring port of the
|
|
75
|
-
Control Server. At this point the socket (that will connect to the
|
|
76
|
-
monitoring port) is not created yet.
|
|
77
|
-
"""
|
|
78
|
-
|
|
79
|
-
super(ConfigurationMonitoringWorker, self).__init__()
|
|
80
|
-
|
|
81
|
-
self.setup = None # Previous setup
|
|
82
|
-
self.obsid = None # Previous obsid
|
|
83
|
-
self.active = False
|
|
84
|
-
|
|
85
|
-
self.connect_socket()
|
|
86
|
-
|
|
87
|
-
def connect_socket(self):
|
|
88
|
-
""" Create a socket and connect to the monitoring port.
|
|
89
|
-
|
|
90
|
-
Args:
|
|
91
|
-
- proxy_type: Proxy type (needed to read the connection details).
|
|
92
|
-
"""
|
|
93
|
-
|
|
94
|
-
# Start listening to the monitoring port
|
|
95
|
-
|
|
96
|
-
self.socket = zmq.Context().socket(zmq.SUB)
|
|
97
|
-
|
|
98
|
-
cm = ConfigurationManagerProxy()
|
|
99
|
-
endpoint = cm.get_endpoint()
|
|
100
|
-
monitoring_port = cm.get_monitoring_port()
|
|
101
|
-
address = set_address_port(endpoint, monitoring_port)
|
|
102
|
-
|
|
103
|
-
self.socket.connect(address)
|
|
104
|
-
self.socket.setsockopt_string(zmq.SUBSCRIBE, "")
|
|
105
|
-
|
|
106
|
-
def start_process(self):
|
|
107
|
-
""" Start listening on the monitoring port.
|
|
108
|
-
"""
|
|
109
|
-
|
|
110
|
-
self.run()
|
|
111
|
-
|
|
112
|
-
@pyqtSlot()
|
|
113
|
-
def run(self):
|
|
114
|
-
""" Keep on listening on the monitoring port.
|
|
115
|
-
|
|
116
|
-
If monitoring information is received before the timeout, it is
|
|
117
|
-
checked whether the obsid and/or current setup have changed. If so, a
|
|
118
|
-
signal with the monitoring information is emitted.
|
|
119
|
-
"""
|
|
120
|
-
|
|
121
|
-
self.active = True
|
|
122
|
-
|
|
123
|
-
while self.active:
|
|
124
|
-
|
|
125
|
-
pickle_string = self.socket.recv()
|
|
126
|
-
monitoring_info = pickle.loads(pickle_string)
|
|
127
|
-
|
|
128
|
-
new_setup = monitoring_info["setup"] # New setup
|
|
129
|
-
|
|
130
|
-
# The setup has changed
|
|
131
|
-
|
|
132
|
-
if new_setup != self.setup:
|
|
133
|
-
|
|
134
|
-
self.setup = new_setup
|
|
135
|
-
|
|
136
|
-
# Emit the setup ID
|
|
137
|
-
|
|
138
|
-
self.setup_changed_signal.emit(self.setup)
|
|
139
|
-
|
|
140
|
-
new_obsid = monitoring_info["obsid"] # New obsid
|
|
141
|
-
|
|
142
|
-
if new_obsid != self.obsid:
|
|
143
|
-
|
|
144
|
-
self.obsid = new_obsid
|
|
145
|
-
|
|
146
|
-
# Emit the obsid
|
|
147
|
-
|
|
148
|
-
self.obsid_changed_signal.emit(self.obsid)
|
|
149
|
-
|
|
150
|
-
def has_setup(self):
|
|
151
|
-
""" Check whether a setup has been loaded.
|
|
152
|
-
|
|
153
|
-
Returns: True if a setup has been loaded; False otherwise.
|
|
154
|
-
"""
|
|
155
|
-
|
|
156
|
-
return self.setup is not None
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
class MonitoringWorker(QObject):
|
|
160
|
-
""" Worker for monitoring the status of an EGSE process."""
|
|
161
|
-
|
|
162
|
-
# The worker will send a signal with the following information:
|
|
163
|
-
# - process name
|
|
164
|
-
# - colour of the led (in the process widget)
|
|
165
|
-
# - in case of a running device process: whether or not it is running in simulator mode
|
|
166
|
-
|
|
167
|
-
process_status_signal = pyqtSignal(dict)
|
|
168
|
-
|
|
169
|
-
def __init__(self, process_name, process_info):
|
|
170
|
-
""" Initialisation of a monitoring worker.
|
|
171
|
-
|
|
172
|
-
This monitoring worker will listen on the monitoring port of the Control Server.
|
|
173
|
-
|
|
174
|
-
Args:
|
|
175
|
-
- process_name: Name of the process.
|
|
176
|
-
- proxy_type: Proxy type (needed to read the connection details).
|
|
177
|
-
"""
|
|
178
|
-
|
|
179
|
-
super(MonitoringWorker, self).__init__()
|
|
180
|
-
|
|
181
|
-
self.active = False
|
|
182
|
-
self.start_stop_cs_button_clicked = False
|
|
183
|
-
|
|
184
|
-
self.process_name = process_name
|
|
185
|
-
self.proxy_type = process_info[0]
|
|
186
|
-
self.proxy_type_as_type = find_class(self.proxy_type[7:])
|
|
187
|
-
self.device_args = process_info[1]
|
|
188
|
-
|
|
189
|
-
self.monitoring_socket = None
|
|
190
|
-
self.monitoring_timeout = 0.5 # [s]
|
|
191
|
-
self.is_socket_connected = False
|
|
192
|
-
|
|
193
|
-
self.commanding_address = None
|
|
194
|
-
self.connect_socket()
|
|
195
|
-
|
|
196
|
-
self.previous_state = -1
|
|
197
|
-
|
|
198
|
-
def connect_socket(self):
|
|
199
|
-
""" Create a socket and connect to the monitoring port."""
|
|
200
|
-
|
|
201
|
-
try:
|
|
202
|
-
|
|
203
|
-
module_name = self.proxy_type[7:].rsplit(".", 1)[0]
|
|
204
|
-
module = importlib.import_module(module_name)
|
|
205
|
-
|
|
206
|
-
# Ctrl settings:
|
|
207
|
-
# - transport protocol
|
|
208
|
-
# - hostname
|
|
209
|
-
# - commanding port (to check whether the CS is active)
|
|
210
|
-
# - monitoring port (to ask for process information)
|
|
211
|
-
|
|
212
|
-
ctrl_settings = module.CTRL_SETTINGS
|
|
213
|
-
|
|
214
|
-
transport = ctrl_settings.PROTOCOL
|
|
215
|
-
hostname = ctrl_settings.HOSTNAME
|
|
216
|
-
|
|
217
|
-
if module_name == "egse.aeu.aeu" or "egse.tempcontrol.agilent.agilent3497" in module_name:
|
|
218
|
-
|
|
219
|
-
name = self.process_name.split(" ")[1].upper()
|
|
220
|
-
|
|
221
|
-
commanding_port = ctrl_settings[name]["COMMANDING_PORT"]
|
|
222
|
-
monitoring_port = ctrl_settings[name]["MONITORING_PORT"]
|
|
223
|
-
|
|
224
|
-
elif module_name == "egse.powermeter.ni.cdaq9184":
|
|
225
|
-
commanding_port = ctrl_settings.CDAQ9184["COMMANDING_PORT"]
|
|
226
|
-
monitoring_port = ctrl_settings.CDAQ9184["MONITORING_PORT"]
|
|
227
|
-
|
|
228
|
-
elif module_name == "egse.tempcontrol.lakeshore.lsci":
|
|
229
|
-
name = "LS_" + self.process_name.split(" ")[2].upper()
|
|
230
|
-
commanding_port = ctrl_settings[name]["COMMANDING_PORT"]
|
|
231
|
-
monitoring_port = ctrl_settings[name]["MONITORING_PORT"]
|
|
232
|
-
|
|
233
|
-
else:
|
|
234
|
-
commanding_port = ctrl_settings.COMMANDING_PORT
|
|
235
|
-
monitoring_port = ctrl_settings.MONITORING_PORT
|
|
236
|
-
|
|
237
|
-
# Create a socket and connect to the monitoring port
|
|
238
|
-
|
|
239
|
-
monitoring_address = connect_address(transport, hostname, monitoring_port)
|
|
240
|
-
self.monitoring_socket = zmq.Context().socket(zmq.SUB)
|
|
241
|
-
self.monitoring_socket.connect(monitoring_address)
|
|
242
|
-
self.monitoring_socket.setsockopt_string(zmq.SUBSCRIBE, "")
|
|
243
|
-
|
|
244
|
-
# Address of the commanding port
|
|
245
|
-
# This is needed when checking whether or not the CS is active
|
|
246
|
-
|
|
247
|
-
self.commanding_address = connect_address(transport, hostname, commanding_port)
|
|
248
|
-
|
|
249
|
-
self.is_socket_connected = True
|
|
250
|
-
|
|
251
|
-
except AttributeError:
|
|
252
|
-
|
|
253
|
-
self.is_socket_connected = False
|
|
254
|
-
|
|
255
|
-
def stop(self):
|
|
256
|
-
|
|
257
|
-
""" Stop the monitoring worker.
|
|
258
|
-
|
|
259
|
-
The monitoring socket is disconnected from the monitoring port and is then closed immediately.
|
|
260
|
-
"""
|
|
261
|
-
|
|
262
|
-
self.is_socket_connected = False
|
|
263
|
-
self.monitoring_socket.close()
|
|
264
|
-
|
|
265
|
-
# self.monitoring_socket.disconnect(self.monitoring_address)
|
|
266
|
-
# self.monitoring_socket.close(linger=0)
|
|
267
|
-
|
|
268
|
-
def start_process(self):
|
|
269
|
-
""" Start listening on the monitoring port.
|
|
270
|
-
|
|
271
|
-
If the Control Server is not active when the thread starts listening on the monitoring port, a signal is emitted
|
|
272
|
-
to notify the GUI.
|
|
273
|
-
"""
|
|
274
|
-
|
|
275
|
-
if not is_control_server_active(self.commanding_address, 0.5):
|
|
276
|
-
|
|
277
|
-
# Emit a signal, indicating the CS is not running
|
|
278
|
-
|
|
279
|
-
process_status = {"Name": self.process_name, "Color": Indic.RED}
|
|
280
|
-
self.previous_state = Indic.RED
|
|
281
|
-
|
|
282
|
-
self.process_status_signal.emit(process_status)
|
|
283
|
-
|
|
284
|
-
self.run()
|
|
285
|
-
|
|
286
|
-
@pyqtSlot()
|
|
287
|
-
def run(self):
|
|
288
|
-
""" Keep on listening on the monitoring port.
|
|
289
|
-
|
|
290
|
-
If monitoring information is received before the timeout, a signal with the monitoring information is emitted.
|
|
291
|
-
Otherwise, it is checked whether or not the Control Server is active. If not, a signal is emitted with the
|
|
292
|
-
process name. Otherwise, the timeout for monitoring was too strict (and it will therefore be increased by
|
|
293
|
-
0.5s).
|
|
294
|
-
"""
|
|
295
|
-
|
|
296
|
-
self.active = True
|
|
297
|
-
|
|
298
|
-
while self.is_socket_connected and self.active:
|
|
299
|
-
|
|
300
|
-
process_status = {"Name": self.process_name}
|
|
301
|
-
|
|
302
|
-
try:
|
|
303
|
-
|
|
304
|
-
socket_list, _, _ = zmq.select([self.monitoring_socket], [], [], timeout=self.monitoring_timeout)
|
|
305
|
-
|
|
306
|
-
# Monitoring information was received (before timeout)
|
|
307
|
-
|
|
308
|
-
if self.monitoring_socket in socket_list:
|
|
309
|
-
|
|
310
|
-
pickle_string = self.monitoring_socket.recv()
|
|
311
|
-
monitoring_info = pickle.loads(pickle_string)
|
|
312
|
-
|
|
313
|
-
# Update the timeout, to be more in line with the monitoring
|
|
314
|
-
# frequency of the CS (i.e. the delay). Take 0.5s extra to be
|
|
315
|
-
# on the safe side.
|
|
316
|
-
|
|
317
|
-
self.monitoring_timeout = monitoring_info["delay"] / 1000.0 + 0.5 # [s]
|
|
318
|
-
|
|
319
|
-
# Running core CS
|
|
320
|
-
|
|
321
|
-
if self.process_name in ["Logger", "Storage", "Configuration Manager", "Process Manager",
|
|
322
|
-
"Synoptics Manager"]:
|
|
323
|
-
process_status["Color"] = Indic.GREEN
|
|
324
|
-
|
|
325
|
-
# Running device CS
|
|
326
|
-
|
|
327
|
-
else:
|
|
328
|
-
process_status["Color"], process_status["Simulator"] = self.get_device_process_status()
|
|
329
|
-
|
|
330
|
-
if not issubclass(self.proxy_type_as_type, DeviceInterface):
|
|
331
|
-
process_status.pop("Simulator")
|
|
332
|
-
|
|
333
|
-
if self.previous_state != process_status["Color"]:
|
|
334
|
-
|
|
335
|
-
self.process_status_signal.emit(process_status)
|
|
336
|
-
self.previous_state = process_status["Color"]
|
|
337
|
-
|
|
338
|
-
except zmq.ZMQError:
|
|
339
|
-
pass
|
|
340
|
-
|
|
341
|
-
# Timeout occurred
|
|
342
|
-
|
|
343
|
-
else:
|
|
344
|
-
|
|
345
|
-
# The CS is not active
|
|
346
|
-
|
|
347
|
-
if not is_control_server_active(endpoint=self.commanding_address, timeout=10):
|
|
348
|
-
|
|
349
|
-
process_status["Color"] = Indic.RED
|
|
350
|
-
|
|
351
|
-
if self.previous_state != process_status["Color"]:
|
|
352
|
-
|
|
353
|
-
self.process_status_signal.emit(process_status)
|
|
354
|
-
self.previous_state = process_status["Color"]
|
|
355
|
-
|
|
356
|
-
elif self.start_stop_cs_button_clicked:
|
|
357
|
-
|
|
358
|
-
self.process_status_signal.emit(process_status)
|
|
359
|
-
self.previous_state = process_status["Color"]
|
|
360
|
-
self.start_stop_cs_button_clicked = False
|
|
361
|
-
|
|
362
|
-
# The CS is active, but the timeout was too strict
|
|
363
|
-
|
|
364
|
-
else:
|
|
365
|
-
self.monitoring_timeout += 0.5
|
|
366
|
-
|
|
367
|
-
def get_device_process_status(self):
|
|
368
|
-
""" Determine the status of the device Control Server.
|
|
369
|
-
|
|
370
|
-
Returns:
|
|
371
|
-
- color: Colour of the led light (to use in the process widget).
|
|
372
|
-
- is_simulator: Whether or not the Control Server is running in simulator mode.
|
|
373
|
-
"""
|
|
374
|
-
|
|
375
|
-
color = Indic.BLACK
|
|
376
|
-
is_simulator = False
|
|
377
|
-
|
|
378
|
-
# Core process -> green
|
|
379
|
-
|
|
380
|
-
try:
|
|
381
|
-
|
|
382
|
-
with find_class(self.proxy_type)(*self.device_args) as process_proxy:
|
|
383
|
-
|
|
384
|
-
# CS that are supposed to connect to a H/W unit (controller)
|
|
385
|
-
|
|
386
|
-
if isinstance(process_proxy, DeviceInterface):
|
|
387
|
-
|
|
388
|
-
try:
|
|
389
|
-
|
|
390
|
-
# CS connected to Controller -> green
|
|
391
|
-
|
|
392
|
-
if process_proxy.is_connected():
|
|
393
|
-
color = Indic.GREEN
|
|
394
|
-
|
|
395
|
-
# CS not connected to Controller -> orange
|
|
396
|
-
|
|
397
|
-
else:
|
|
398
|
-
color = Indic.ORANGE
|
|
399
|
-
|
|
400
|
-
except AttributeError:
|
|
401
|
-
color = Indic.GREEN
|
|
402
|
-
|
|
403
|
-
is_simulator = process_proxy.is_simulator()
|
|
404
|
-
|
|
405
|
-
# CS that do not control any device (e.g. FDIR, alert manager, etc.)
|
|
406
|
-
|
|
407
|
-
else:
|
|
408
|
-
color = Indic.GREEN
|
|
409
|
-
is_simulator = False
|
|
410
|
-
|
|
411
|
-
except ConnectionError:
|
|
412
|
-
pass
|
|
413
|
-
|
|
414
|
-
return color, is_simulator
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
class ProcessMonitoringWorker(QObject):
|
|
418
|
-
""" Worker for monitoring the status of a process."""
|
|
419
|
-
|
|
420
|
-
is_running_signal = pyqtSignal(bool)
|
|
421
|
-
|
|
422
|
-
def __init__(self, module):
|
|
423
|
-
""" Worker for monitoring the status of a process.
|
|
424
|
-
|
|
425
|
-
Args:
|
|
426
|
-
- module
|
|
427
|
-
"""
|
|
428
|
-
|
|
429
|
-
super(ProcessMonitoringWorker, self).__init__()
|
|
430
|
-
|
|
431
|
-
self.active = False
|
|
432
|
-
self.start_stop_cs_button_clicked = False
|
|
433
|
-
|
|
434
|
-
self.was_running_before = None
|
|
435
|
-
|
|
436
|
-
self.module = importlib.import_module(module)
|
|
437
|
-
|
|
438
|
-
def start_process(self):
|
|
439
|
-
""" Start listening on the monitoring port.
|
|
440
|
-
|
|
441
|
-
If the Control Server is not active when the thread starts listening on the monitoring port, a signal is emitted
|
|
442
|
-
to notify the GUI.
|
|
443
|
-
"""
|
|
444
|
-
|
|
445
|
-
self.run()
|
|
446
|
-
|
|
447
|
-
@pyqtSlot()
|
|
448
|
-
def run(self):
|
|
449
|
-
""" Keep on asking for the status of the status of the process.
|
|
450
|
-
|
|
451
|
-
Every 5s, ask for the status of the process. If this changes w.r.t. of they way it was before, a signal is
|
|
452
|
-
emitted with the current status.
|
|
453
|
-
"""
|
|
454
|
-
|
|
455
|
-
self.active = True
|
|
456
|
-
last_time = time.time()
|
|
457
|
-
|
|
458
|
-
while self.active:
|
|
459
|
-
|
|
460
|
-
if time.time() - last_time >= 5:
|
|
461
|
-
|
|
462
|
-
is_running = self.module.send_request("status").get("status") == "ACK"
|
|
463
|
-
|
|
464
|
-
if is_running != self.was_running_before:
|
|
465
|
-
self.was_running_before = is_running
|
|
466
|
-
self.is_running_signal.emit(is_running)
|
|
467
|
-
|
|
468
|
-
elif self.start_stop_cs_button_clicked:
|
|
469
|
-
|
|
470
|
-
for index in range(15):
|
|
471
|
-
|
|
472
|
-
# Check (max 15x) to see whether pressing the button had an effect
|
|
473
|
-
|
|
474
|
-
is_running = self.module.send_request("status").get("status") == "ACK"
|
|
475
|
-
if self.was_running_before != is_running:
|
|
476
|
-
break
|
|
477
|
-
time.sleep(2)
|
|
478
|
-
|
|
479
|
-
self.was_running_before = is_running
|
|
480
|
-
self.start_stop_cs_button_clicked = False
|
|
481
|
-
self.is_running_signal.emit(is_running)
|
|
482
|
-
|
|
483
|
-
last_time = time.time()
|
|
484
|
-
|
|
485
|
-
else:
|
|
486
|
-
time.sleep(0.1)
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
class ProcessWidget(QGroupBox):
|
|
490
|
-
|
|
491
|
-
def __init__(self, process_name, process_info, parent, include_start_stop_button=True):
|
|
492
|
-
""" Initialisation of a process widget.
|
|
493
|
-
|
|
494
|
-
For a Control Server with the given process name and Proxy type, a process widget is created. This widget will
|
|
495
|
-
comprise the following components:
|
|
496
|
-
|
|
497
|
-
- status LED;
|
|
498
|
-
- process name;
|
|
499
|
-
- button to start the GUI for the Control Server (if this has been
|
|
500
|
-
configured in the YAML file with the "UserInterface" entry);
|
|
501
|
-
- button to start / shut down the Control Server (for devices only).
|
|
502
|
-
|
|
503
|
-
Args:
|
|
504
|
-
- process_name: Name of the process (to display on the widget).
|
|
505
|
-
- proxy_type: Type of Proxy (to check the status of the process).
|
|
506
|
-
"""
|
|
507
|
-
|
|
508
|
-
super().__init__()
|
|
509
|
-
|
|
510
|
-
self.process_name = process_name
|
|
511
|
-
self.proxy_type = process_info[0]
|
|
512
|
-
self.proxy_type_as_type = find_class(self.proxy_type[7:])
|
|
513
|
-
self.device_args = process_info[1]
|
|
514
|
-
self.is_simulator_mode = False
|
|
515
|
-
self.is_device = True
|
|
516
|
-
|
|
517
|
-
self.parent = parent
|
|
518
|
-
|
|
519
|
-
layout = QGridLayout()
|
|
520
|
-
|
|
521
|
-
index = 0
|
|
522
|
-
|
|
523
|
-
# Status LED
|
|
524
|
-
|
|
525
|
-
self.status_led = LED(parent=self)
|
|
526
|
-
layout.addWidget(self.status_led, 0, index)
|
|
527
|
-
index += 1
|
|
528
|
-
|
|
529
|
-
# Process name
|
|
530
|
-
|
|
531
|
-
self.process_name_label = QLabel(process_name)
|
|
532
|
-
layout.addWidget(self.process_name_label, 0, index)
|
|
533
|
-
layout.setColumnStretch(index, 1) # Push LED and name to the left and buttons to the right
|
|
534
|
-
index += 1
|
|
535
|
-
|
|
536
|
-
# Fire up (default) GUI
|
|
537
|
-
|
|
538
|
-
self.show_gui_button = TouchButton(name=f"Open the GUI for the {self.process_name}.",
|
|
539
|
-
status_tip=f"Open the GUI for the {self.process_name}.",
|
|
540
|
-
selected=get_resource(":/icons/user-interface.svg")
|
|
541
|
-
)
|
|
542
|
-
self.show_gui_button.setFixedSize(30, 30)
|
|
543
|
-
self.show_gui_button.clicked.connect(self.start_gui)
|
|
544
|
-
|
|
545
|
-
module_name = self.proxy_type[7:].rsplit(".", 1)[0]
|
|
546
|
-
module = importlib.import_module(module_name)
|
|
547
|
-
|
|
548
|
-
if not process_name.startswith("AEU") or process_name == "AEU cRIO":
|
|
549
|
-
|
|
550
|
-
if hasattr(module, "DEVICE_SETTINGS") and hasattr(module.DEVICE_SETTINGS, "UserInterface"):
|
|
551
|
-
layout.addWidget(self.show_gui_button, 0, index)
|
|
552
|
-
elif hasattr(module, "COMMAND_SETTINGS") and hasattr(module.COMMAND_SETTINGS, "UserInterface"):
|
|
553
|
-
layout.addWidget(self.show_gui_button, 0, index)
|
|
554
|
-
|
|
555
|
-
index += 1
|
|
556
|
-
|
|
557
|
-
# Shut down / re-start
|
|
558
|
-
|
|
559
|
-
if include_start_stop_button:
|
|
560
|
-
|
|
561
|
-
self.start_stop_button = ToggleButton(name=f"Start / shut down the {self.process_name} control server.",
|
|
562
|
-
status_tip=f"Start / shut down the {self.process_name} control server.",
|
|
563
|
-
selected=get_resource(":/images/play-button.svg"),
|
|
564
|
-
not_selected=get_resource(":/images/stop-button.svg"),
|
|
565
|
-
disabled=[get_resource(":/icons/busy.svg"),
|
|
566
|
-
get_resource(":/icons/busy.svg")]
|
|
567
|
-
)
|
|
568
|
-
self.start_stop_button.clicked.connect(self.start_stop_cs)
|
|
569
|
-
|
|
570
|
-
layout.addWidget(self.start_stop_button, 0, index)
|
|
571
|
-
index += 1
|
|
572
|
-
|
|
573
|
-
if issubclass(self.proxy_type_as_type, DeviceInterface):
|
|
574
|
-
self.sim_option_button = ToggleButton(name=f"Operational vs. simulator mode",
|
|
575
|
-
status_tip=f"Indicate whether you want to start the "
|
|
576
|
-
f"{self.process_name} Control Server in operational or in "
|
|
577
|
-
f"simulator mode.",
|
|
578
|
-
selected=get_resource(":/icons/sim-mode.svg"),
|
|
579
|
-
not_selected=get_resource(":/icons/ops-mode.svg"),
|
|
580
|
-
disabled=[get_resource(":/icons/sim-mode.svg"),
|
|
581
|
-
get_resource(":/icons/ops-mode.svg")]
|
|
582
|
-
)
|
|
583
|
-
self.sim_option_button.set_selected(False) # Default: operational mode
|
|
584
|
-
else:
|
|
585
|
-
self.sim_option_button = ToggleButton(name=f"Operational vs. simulator mode",
|
|
586
|
-
status_tip=f"The {self.process_name} Control Server can only be "
|
|
587
|
-
f"started in operational mode.",
|
|
588
|
-
selected=get_resource(":/icons/ops-mode.svg"),
|
|
589
|
-
not_selected=get_resource(":/icons/ops-mode.svg"),
|
|
590
|
-
disabled=[get_resource(":/icons/ops-mode.svg"),
|
|
591
|
-
get_resource(":/icons/ops-mode.svg")]
|
|
592
|
-
)
|
|
593
|
-
self.is_device = False
|
|
594
|
-
self.sim_option_button.clicked.connect(self.set_cs_start_mode)
|
|
595
|
-
|
|
596
|
-
if self.process_name == "DAQ":
|
|
597
|
-
|
|
598
|
-
self.start_stop_button.setToolTip(f"Start / shut down the {self.process_name} control server and its "
|
|
599
|
-
f"data acquisition.")
|
|
600
|
-
self.sim_option_button.setEnabled(False) # Only in operational mode
|
|
601
|
-
self.sim_option_button.setStatusTip(f"The {self.process_name} and its data acquisition can only be"
|
|
602
|
-
f"started in operational mode.")
|
|
603
|
-
|
|
604
|
-
layout.addWidget(self.sim_option_button, 0, index)
|
|
605
|
-
index += 1
|
|
606
|
-
|
|
607
|
-
self.setLayout(layout)
|
|
608
|
-
|
|
609
|
-
def start_gui(self):
|
|
610
|
-
""" Starting the default GUI for the process."""
|
|
611
|
-
|
|
612
|
-
LOGGER.debug(f"Starting GUI for {self.process_name}")
|
|
613
|
-
|
|
614
|
-
module_name = self.proxy_type[7:].rsplit(".", 1)[0]
|
|
615
|
-
module = importlib.import_module(module_name)
|
|
616
|
-
|
|
617
|
-
if hasattr(module, "DEVICE_SETTINGS") and hasattr(module.DEVICE_SETTINGS, "UserInterface"):
|
|
618
|
-
gui_type = module.DEVICE_SETTINGS.UserInterface # Device CS
|
|
619
|
-
elif hasattr(module, "COMMAND_SETTINGS") and hasattr(module.COMMAND_SETTINGS, "UserInterface"):
|
|
620
|
-
gui_type = module.COMMAND_SETTINGS.UserInterface # Core CS
|
|
621
|
-
else: # No GUI defined in the YAML file of the CS
|
|
622
|
-
LOGGER.debug(f"No GUI available for {self.process_name}")
|
|
623
|
-
return
|
|
624
|
-
if module_name == "egse.tempcontrol.lakeshore.lsci":
|
|
625
|
-
index = self.process_name.split(" ")[2]
|
|
626
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m", gui_type, "--index", index])
|
|
627
|
-
gui_process.execute(detach_from_parent=True)
|
|
628
|
-
else:
|
|
629
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m", gui_type])
|
|
630
|
-
gui_process.execute(detach_from_parent=True)
|
|
631
|
-
|
|
632
|
-
def set_cs_start_mode(self):
|
|
633
|
-
""" Change the start mode for the Control Server.
|
|
634
|
-
|
|
635
|
-
Change the start mode for the Control Server from simulator mode to operational mode, or vice versa.
|
|
636
|
-
"""
|
|
637
|
-
self.is_simulator_mode = not self.is_simulator_mode
|
|
638
|
-
|
|
639
|
-
def start_stop_cs(self):
|
|
640
|
-
""" Start or shut down the Control Server.
|
|
641
|
-
|
|
642
|
-
Depending on the current state of the Control Server, it will either be started or shut down.
|
|
643
|
-
"""
|
|
644
|
-
|
|
645
|
-
self.sim_option_button.setEnabled(False)
|
|
646
|
-
self.start_stop_button.setDisabled(True)
|
|
647
|
-
|
|
648
|
-
if self.start_stop_button.is_selected():
|
|
649
|
-
|
|
650
|
-
LOGGER.info(f"Shut down the {self.process_name} Control Server")
|
|
651
|
-
thread = threading.Thread(target=self.stop_cs)
|
|
652
|
-
|
|
653
|
-
else:
|
|
654
|
-
|
|
655
|
-
LOGGER.info(f"Start the {self.process_name} Control Server")
|
|
656
|
-
thread = threading.Thread(target=self.start_cs)
|
|
657
|
-
|
|
658
|
-
thread.daemon = True
|
|
659
|
-
thread.start()
|
|
660
|
-
|
|
661
|
-
# Let the main UI window know that the start/stop button has been clicked
|
|
662
|
-
self.parent.on_start_stop_cs_button_clicked(self.process_name)
|
|
663
|
-
|
|
664
|
-
def start_cs(self):
|
|
665
|
-
|
|
666
|
-
try:
|
|
667
|
-
|
|
668
|
-
with ProcessManagerProxy() as pm:
|
|
669
|
-
|
|
670
|
-
response: Response = pm.start_cs(self.process_name, self.is_simulator_mode)
|
|
671
|
-
if response.successful:
|
|
672
|
-
self.sim_option_button.setDisabled(True)
|
|
673
|
-
else:
|
|
674
|
-
self.sim_option_button.setEnabled(True)
|
|
675
|
-
|
|
676
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m", "egse.procman.cannot_start_process_popup",
|
|
677
|
-
"--process_name", f"{self.process_name} Control Server",
|
|
678
|
-
"--message", response.message])
|
|
679
|
-
gui_process.execute(detach_from_parent=True)
|
|
680
|
-
|
|
681
|
-
return response
|
|
682
|
-
|
|
683
|
-
#
|
|
684
|
-
# try:
|
|
685
|
-
# pm.start_cs(self.process_name, self.is_simulator_mode)
|
|
686
|
-
# self.sim_option_button.setDisabled(True)
|
|
687
|
-
#
|
|
688
|
-
# except ConnectionError:
|
|
689
|
-
# LOGGER.info(f"Could not start Control Server for {self.process_name}")
|
|
690
|
-
# self.sim_option_button.setEnabled(True)
|
|
691
|
-
#
|
|
692
|
-
except ConnectionError as exc:
|
|
693
|
-
|
|
694
|
-
message = f"Lost connection to Process Manager"
|
|
695
|
-
LOGGER.critical(message, exc_info=True)
|
|
696
|
-
|
|
697
|
-
self.sim_option_button.setEnabled(True)
|
|
698
|
-
self.start_stop_button.setEnabled(True)
|
|
699
|
-
self.start_stop_button.set_selected(True)
|
|
700
|
-
|
|
701
|
-
return Failure(message, cause=exc)
|
|
702
|
-
|
|
703
|
-
def stop_cs(self):
|
|
704
|
-
|
|
705
|
-
try:
|
|
706
|
-
with ProcessManagerProxy() as pm:
|
|
707
|
-
LOGGER.info(f"PM: shut down {self.process_name}")
|
|
708
|
-
pm.shut_down_cs(self.process_name)
|
|
709
|
-
self.sim_option_button.setDisabled(False)
|
|
710
|
-
|
|
711
|
-
except ConnectionError:
|
|
712
|
-
|
|
713
|
-
LOGGER.critical(f"Lost connection to Process Manager")
|
|
714
|
-
self.sim_option_button.setEnabled(True)
|
|
715
|
-
|
|
716
|
-
def set_led_color(self, color: int):
|
|
717
|
-
""" Set the colour of the LED, representing the status of the process.
|
|
718
|
-
|
|
719
|
-
The meaning of the colours is the following:
|
|
720
|
-
|
|
721
|
-
- green:
|
|
722
|
-
- core process with running Control Server;
|
|
723
|
-
- device process in simulator mode with running Control Server;
|
|
724
|
-
- device process in operational mode with running Control Server and connection to the Controller;
|
|
725
|
-
- orange: device process in operational mode with Control Server running but without connection to the
|
|
726
|
-
Controller;
|
|
727
|
-
- red: no Control Server running.
|
|
728
|
-
|
|
729
|
-
Args:
|
|
730
|
-
- color: Integer representing the colour to indicate the process status. Should only be Indic.GREEN,
|
|
731
|
-
Indic.ORANGE, or Indic.RED.
|
|
732
|
-
"""
|
|
733
|
-
|
|
734
|
-
self.status_led.set_color(color)
|
|
735
|
-
|
|
736
|
-
try:
|
|
737
|
-
self.start_stop_button.setDisabled(False)
|
|
738
|
-
except AttributeError:
|
|
739
|
-
# Core processes don't have this button
|
|
740
|
-
pass
|
|
741
|
-
|
|
742
|
-
if color != Indic.RED:
|
|
743
|
-
try:
|
|
744
|
-
self.sim_option_button.setEnabled(False)
|
|
745
|
-
self.start_stop_button.set_selected(False)
|
|
746
|
-
except AttributeError:
|
|
747
|
-
# Core processes don't have this button
|
|
748
|
-
pass
|
|
749
|
-
|
|
750
|
-
else:
|
|
751
|
-
try:
|
|
752
|
-
self.sim_option_button.setEnabled(True)
|
|
753
|
-
self.start_stop_button.set_selected(True)
|
|
754
|
-
except AttributeError:
|
|
755
|
-
# Core processes don't have this button
|
|
756
|
-
pass
|
|
757
|
-
|
|
758
|
-
def is_simulator_mode(self):
|
|
759
|
-
""" Check whether the simulator mode checkbox was checked.
|
|
760
|
-
|
|
761
|
-
Returns: True of the simulator mode checkbox was checked; False otherwise.
|
|
762
|
-
"""
|
|
763
|
-
|
|
764
|
-
return self.sim_option_button.is_selected()
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
class NonCSProcessWidget(QGroupBox):
|
|
768
|
-
|
|
769
|
-
def __init__(self, process_name, parent, include_gui_button=True, include_start_stop_button=True):
|
|
770
|
-
""" Initialisation of a process widget.
|
|
771
|
-
|
|
772
|
-
For a Control Server with the given process name and Proxy type, a process widget is created. This widget will
|
|
773
|
-
comprise the following components:
|
|
774
|
-
|
|
775
|
-
- status LED;
|
|
776
|
-
- process name;
|
|
777
|
-
- button to start the GUI for the process;
|
|
778
|
-
- button to start / shut down the process.
|
|
779
|
-
|
|
780
|
-
Args:
|
|
781
|
-
- process_name: Name of the process (to display on the widget).
|
|
782
|
-
"""
|
|
783
|
-
|
|
784
|
-
super().__init__()
|
|
785
|
-
|
|
786
|
-
self.process_name = process_name
|
|
787
|
-
self.parent = parent
|
|
788
|
-
|
|
789
|
-
layout = QGridLayout()
|
|
790
|
-
|
|
791
|
-
index = 0
|
|
792
|
-
|
|
793
|
-
# Status LED
|
|
794
|
-
|
|
795
|
-
self.status_led = LED(parent=self)
|
|
796
|
-
layout.addWidget(self.status_led, 0, index)
|
|
797
|
-
index += 1
|
|
798
|
-
|
|
799
|
-
# Process name
|
|
800
|
-
|
|
801
|
-
self.process_name_label = QLabel(process_name)
|
|
802
|
-
layout.addWidget(self.process_name_label, 0, index)
|
|
803
|
-
layout.setColumnStretch(index, 1) # Push LED and name to the left and buttons to the right
|
|
804
|
-
index += 1
|
|
805
|
-
|
|
806
|
-
# Fire up (default) GUI
|
|
807
|
-
|
|
808
|
-
if include_gui_button:
|
|
809
|
-
|
|
810
|
-
self.show_gui_button = TouchButton(name=f"Open the GUI for the {self.process_name}.",
|
|
811
|
-
status_tip=f"Open the GUI for the {self.process_name}.",
|
|
812
|
-
selected=get_resource(":/icons/user-interface.svg")
|
|
813
|
-
)
|
|
814
|
-
self.show_gui_button.setFixedSize(30, 30)
|
|
815
|
-
layout.addWidget(self.show_gui_button, 0, index)
|
|
816
|
-
self.show_gui_button.clicked.connect(self.start_gui)
|
|
817
|
-
|
|
818
|
-
index += 1
|
|
819
|
-
|
|
820
|
-
# Shut down / re-start
|
|
821
|
-
|
|
822
|
-
if include_start_stop_button:
|
|
823
|
-
|
|
824
|
-
self.start_stop_button = ToggleButton(name=f"Start / shut down the {self.process_name}.",
|
|
825
|
-
status_tip=f"Start / shut down the {self.process_name}.",
|
|
826
|
-
selected=get_resource(":/images/play-button.svg"),
|
|
827
|
-
not_selected=get_resource(":/images/stop-button.svg"),
|
|
828
|
-
disabled=[get_resource(":/icons/busy.svg"),
|
|
829
|
-
get_resource(":/icons/busy.svg")]
|
|
830
|
-
)
|
|
831
|
-
self.start_stop_button.clicked.connect(self.start_stop_service)
|
|
832
|
-
layout.addWidget(self.start_stop_button, 0, index)
|
|
833
|
-
index += 1
|
|
834
|
-
|
|
835
|
-
self.setLayout(layout)
|
|
836
|
-
|
|
837
|
-
def start_stop_service(self):
|
|
838
|
-
|
|
839
|
-
self.start_stop_button.setDisabled(True)
|
|
840
|
-
|
|
841
|
-
if self.start_stop_button.is_selected():
|
|
842
|
-
|
|
843
|
-
print(f"Stopping {self.process_name}")
|
|
844
|
-
LOGGER.info(f"Shut down the {self.process_name}")
|
|
845
|
-
thread = threading.Thread(target=self.stop_service)
|
|
846
|
-
|
|
847
|
-
else:
|
|
848
|
-
|
|
849
|
-
print(f"Starting {self.process_name}")
|
|
850
|
-
LOGGER.info(f"Start the {self.process_name}")
|
|
851
|
-
thread = threading.Thread(target=self.start_service)
|
|
852
|
-
|
|
853
|
-
thread.daemon = True
|
|
854
|
-
thread.start()
|
|
855
|
-
|
|
856
|
-
self.parent.on_start_stop_non_cs_process_button_clicked(self.process_name)
|
|
857
|
-
|
|
858
|
-
# def start_gui(self):
|
|
859
|
-
# """ Starting the default GUI for the process."""
|
|
860
|
-
#
|
|
861
|
-
# LOGGER.debug(f"Starting GUI for {self.process_name}")
|
|
862
|
-
# print("Starting GUI")
|
|
863
|
-
|
|
864
|
-
def set_led_color(self, color: int):
|
|
865
|
-
""" Set the colour of the LED, representing the status of the process.
|
|
866
|
-
|
|
867
|
-
The meaning of the colours is the following:
|
|
868
|
-
|
|
869
|
-
- green: process running;
|
|
870
|
-
- red: process not running.
|
|
871
|
-
|
|
872
|
-
Args:
|
|
873
|
-
- color: Integer representing the colour to indicate the process status. Should only be Indic.GREEN,
|
|
874
|
-
or Indic.RED.
|
|
875
|
-
"""
|
|
876
|
-
|
|
877
|
-
self.status_led.set_color(color)
|
|
878
|
-
|
|
879
|
-
try:
|
|
880
|
-
self.start_stop_button.setDisabled(False)
|
|
881
|
-
self.start_stop_button.set_selected(color == Indic.RED)
|
|
882
|
-
except AttributeError:
|
|
883
|
-
# The logger doesn't have a start/stop button
|
|
884
|
-
pass
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
class LogWidget(NonCSProcessWidget):
|
|
888
|
-
|
|
889
|
-
def __init__(self, parent):
|
|
890
|
-
|
|
891
|
-
super().__init__("Logger", parent, include_gui_button=True, include_start_stop_button=False)
|
|
892
|
-
|
|
893
|
-
def start_gui(self):
|
|
894
|
-
|
|
895
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m", "cutelog"])
|
|
896
|
-
gui_process.execute(detach_from_parent=True)
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
class FitsgenWidget(NonCSProcessWidget):
|
|
900
|
-
|
|
901
|
-
def __init__(self, parent):
|
|
902
|
-
|
|
903
|
-
super(FitsgenWidget, self).__init__(FILE_GENERATION_PROCESS_NAMES.FITSGEN, parent, include_gui_button=True,
|
|
904
|
-
include_start_stop_button=True)
|
|
905
|
-
|
|
906
|
-
def start_gui(self):
|
|
907
|
-
|
|
908
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m", "egse.dpu.fitsgen_ui"])
|
|
909
|
-
gui_process.execute(detach_from_parent=True)
|
|
910
|
-
|
|
911
|
-
def start_service(self):
|
|
912
|
-
|
|
913
|
-
response: Response = start_fitsgen()
|
|
914
|
-
|
|
915
|
-
if not response.successful:
|
|
916
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m", "egse.procman.cannot_start_process_popup",
|
|
917
|
-
"--process_name", "FITS generation", "--message", response.message])
|
|
918
|
-
gui_process.execute(detach_from_parent=True)
|
|
919
|
-
|
|
920
|
-
def stop_service(self):
|
|
921
|
-
|
|
922
|
-
stop_fitsgen()
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
class FovHkWidget(NonCSProcessWidget):
|
|
926
|
-
|
|
927
|
-
def __init__(self, parent):
|
|
928
|
-
|
|
929
|
-
super(FovHkWidget, self).__init__(FILE_GENERATION_PROCESS_NAMES.FOV_HK, parent, include_gui_button=False,
|
|
930
|
-
include_start_stop_button=True)
|
|
931
|
-
|
|
932
|
-
def start_service(self):
|
|
933
|
-
|
|
934
|
-
response: Response = start_fov_hk()
|
|
935
|
-
|
|
936
|
-
if not response.successful:
|
|
937
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m", "egse.procman.cannot_start_process_popup",
|
|
938
|
-
"--process_name", "FOV HK generation", "--message", response.message])
|
|
939
|
-
gui_process.execute(detach_from_parent=True)
|
|
940
|
-
|
|
941
|
-
def stop_service(self):
|
|
942
|
-
|
|
943
|
-
stop_fov_hk()
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
class NFeeHkWidget(NonCSProcessWidget):
|
|
947
|
-
|
|
948
|
-
def __init__(self, parent):
|
|
949
|
-
|
|
950
|
-
super(NFeeHkWidget, self).__init__(FILE_GENERATION_PROCESS_NAMES.N_FEE_HK, parent, include_gui_button=False,
|
|
951
|
-
include_start_stop_button=True)
|
|
952
|
-
|
|
953
|
-
def start_service(self):
|
|
954
|
-
|
|
955
|
-
response: Response = start_n_fee_hk()
|
|
956
|
-
|
|
957
|
-
if not response.successful:
|
|
958
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m", "egse.procman.cannot_start_process_popup",
|
|
959
|
-
"--process_name", "N-FEE HK generation", "--message", response.message])
|
|
960
|
-
gui_process.execute(detach_from_parent=True)
|
|
961
|
-
|
|
962
|
-
def stop_service(self):
|
|
963
|
-
|
|
964
|
-
stop_n_fee_hk()
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
def start_fitsgen():
|
|
968
|
-
""" Start the FITS generation."""
|
|
969
|
-
|
|
970
|
-
with ProcessManagerProxy() as pm:
|
|
971
|
-
return pm.start_fitsgen()
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
def stop_fitsgen():
|
|
975
|
-
""" Stop the FITS generation."""
|
|
976
|
-
|
|
977
|
-
with ProcessManagerProxy() as pm:
|
|
978
|
-
pm.stop_fitsgen()
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
def start_fov_hk():
|
|
982
|
-
""" Start the generation of FOV HK."""
|
|
983
|
-
|
|
984
|
-
with ProcessManagerProxy() as pm:
|
|
985
|
-
return pm.start_fov_hk()
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
def stop_fov_hk():
|
|
989
|
-
""" Stop the generation of FOV HK"""
|
|
990
|
-
|
|
991
|
-
with ProcessManagerProxy() as pm:
|
|
992
|
-
pm.stop_fov_hk()
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
def start_n_fee_hk():
|
|
996
|
-
""" Start the generation of N-FEE HK."""
|
|
997
|
-
|
|
998
|
-
with ProcessManagerProxy() as pm:
|
|
999
|
-
return pm.start_n_fee_hk()
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
def stop_n_fee_hk():
|
|
1003
|
-
""" Stop the generation of N-FEE HK."""
|
|
1004
|
-
|
|
1005
|
-
with ProcessManagerProxy() as pm:
|
|
1006
|
-
pm.stop_n_fee_hk()
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
def start_egse():
|
|
1010
|
-
""" Start all device Control Servers in one go."""
|
|
1011
|
-
|
|
1012
|
-
with ProcessManagerProxy() as pm:
|
|
1013
|
-
pm.start_egse()
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
def stop_egse():
|
|
1017
|
-
""" Stop all device Control Servers in one go."""
|
|
1018
|
-
|
|
1019
|
-
with ProcessManagerProxy() as pm:
|
|
1020
|
-
pm.shut_down_egse()
|
|
1021
|
-
|
|
1022
|
-
def open_th_ui():
|
|
1023
|
-
""" Open the TH Operator UI."""
|
|
1024
|
-
|
|
1025
|
-
sitehash = {
|
|
1026
|
-
"CSL": get_csl_ui_process,
|
|
1027
|
-
"CSL1": get_csl_ui_process,
|
|
1028
|
-
"CSL2": get_csl_ui_process,
|
|
1029
|
-
"IAS": get_ias_ui_process,
|
|
1030
|
-
"INTA": get_inta_ui_process,
|
|
1031
|
-
"SRON": get_sron_ui_process,
|
|
1032
|
-
}
|
|
1033
|
-
|
|
1034
|
-
gui_process = sitehash[SITE.ID]()
|
|
1035
|
-
gui_process.execute(detach_from_parent=True)
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
def get_csl_ui_process():
|
|
1039
|
-
return SubProcess("MyApp", ["csl_ui"])
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
def get_sron_ui_process():
|
|
1043
|
-
return SubProcess("MyApp", ["sron_ui"])
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
def get_ias_ui_process():
|
|
1047
|
-
return SubProcess("MyApp", ["ias_ui"])
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
def get_inta_ui_process():
|
|
1051
|
-
return SubProcess("MyApp", ["inta_ui"])
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
def open_fov_ui():
|
|
1055
|
-
""" Open the FOV UI."""
|
|
1056
|
-
|
|
1057
|
-
gui_process = SubProcess("MyApp", ["fov_ui"])
|
|
1058
|
-
gui_process.execute(detach_from_parent=True)
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
def open_visited_positions_ui():
|
|
1062
|
-
""" Open the visited-positions UI."""
|
|
1063
|
-
|
|
1064
|
-
gui_process = SubProcess("MyApp", ["visited_positions_ui"])
|
|
1065
|
-
gui_process.execute(detach_from_parent=True)
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
class ProcessManagerUIView(QMainWindow):
|
|
1069
|
-
|
|
1070
|
-
def __init__(self):
|
|
1071
|
-
""" Initialisation of the Process Manager GUI.
|
|
1072
|
-
|
|
1073
|
-
The components are placed in the window and threads are created for all processes, to be able to check for
|
|
1074
|
-
updates in the process status (in the background) and display these in the GUI.
|
|
1075
|
-
"""
|
|
1076
|
-
|
|
1077
|
-
super().__init__()
|
|
1078
|
-
|
|
1079
|
-
self.setGeometry(300, 300, 1000, 1000)
|
|
1080
|
-
self.setWindowTitle("Process Manager")
|
|
1081
|
-
|
|
1082
|
-
self.processes = {}
|
|
1083
|
-
self.devices = {}
|
|
1084
|
-
|
|
1085
|
-
try:
|
|
1086
|
-
|
|
1087
|
-
with ProcessManagerProxy() as process_manager_proxy:
|
|
1088
|
-
|
|
1089
|
-
self.core = process_manager_proxy.get_core() # Core
|
|
1090
|
-
|
|
1091
|
-
except ConnectionError:
|
|
1092
|
-
|
|
1093
|
-
self.core = {}
|
|
1094
|
-
|
|
1095
|
-
self.monitoring_threads = {}
|
|
1096
|
-
self.monitoring_workers = {}
|
|
1097
|
-
|
|
1098
|
-
self.process_widgets = {}
|
|
1099
|
-
|
|
1100
|
-
self.process_widgets_core = {}
|
|
1101
|
-
|
|
1102
|
-
self.setup_monitoring_thread = QThread(self)
|
|
1103
|
-
self.setup_monitoring_worker = ConfigurationMonitoringWorker()
|
|
1104
|
-
self.setup_monitoring_worker.moveToThread(self.setup_monitoring_thread)
|
|
1105
|
-
|
|
1106
|
-
# What to do when information has been received on the monitoring
|
|
1107
|
-
# port before timeout?
|
|
1108
|
-
|
|
1109
|
-
self.setup_monitoring_worker.setup_changed_signal.connect(self.on_setup_changed_signal)
|
|
1110
|
-
self.setup_monitoring_worker.obsid_changed_signal.connect(self.on_obsid_changed_signal)
|
|
1111
|
-
self.setup_monitoring_thread.started.connect(self.setup_monitoring_worker.start_process)
|
|
1112
|
-
self.setup_monitoring_thread.start()
|
|
1113
|
-
|
|
1114
|
-
# Build up the GUI
|
|
1115
|
-
|
|
1116
|
-
self.init_ui()
|
|
1117
|
-
|
|
1118
|
-
# Keep an eye on the logger
|
|
1119
|
-
|
|
1120
|
-
self.logger_monitoring_thread = QThread(self)
|
|
1121
|
-
self.logger_monitoring_worker = ProcessMonitoringWorker("egse.logger.log_cs")
|
|
1122
|
-
self.logger_monitoring_worker.moveToThread(self.logger_monitoring_thread)
|
|
1123
|
-
self.logger_monitoring_worker.is_running_signal.connect(self.on_logger_is_running_signal)
|
|
1124
|
-
self.logger_monitoring_thread.started.connect(self.logger_monitoring_worker.start_process)
|
|
1125
|
-
self.logger_monitoring_thread.start()
|
|
1126
|
-
|
|
1127
|
-
# Keep an eye on the FITS generation
|
|
1128
|
-
|
|
1129
|
-
self.fitsgen_monitoring_thread = QThread(self)
|
|
1130
|
-
self.fitsgen_monitoring_worker = ProcessMonitoringWorker("egse.dpu.fitsgen")
|
|
1131
|
-
self.fitsgen_monitoring_worker.moveToThread(self.fitsgen_monitoring_thread)
|
|
1132
|
-
self.fitsgen_monitoring_worker.is_running_signal.connect(self.on_fitsgen_is_running_signal)
|
|
1133
|
-
self.fitsgen_monitoring_thread.started.connect(self.fitsgen_monitoring_worker.start_process)
|
|
1134
|
-
self.fitsgen_monitoring_thread.start()
|
|
1135
|
-
|
|
1136
|
-
# Keep an eye on the generation of FOV HK
|
|
1137
|
-
|
|
1138
|
-
self.fov_hk_monitoring_thread = QThread(self)
|
|
1139
|
-
self.fov_hk_monitoring_worker = ProcessMonitoringWorker("egse.fov.fov_hk")
|
|
1140
|
-
self.fov_hk_monitoring_worker.moveToThread(self.fov_hk_monitoring_thread)
|
|
1141
|
-
self.fov_hk_monitoring_worker.is_running_signal.connect(self.on_fov_hk_is_running_signal)
|
|
1142
|
-
self.fov_hk_monitoring_thread.started.connect(self.fov_hk_monitoring_worker.start_process)
|
|
1143
|
-
self.fov_hk_monitoring_thread.start()
|
|
1144
|
-
|
|
1145
|
-
# Keep an eye on the generation of N-FEE HK
|
|
1146
|
-
|
|
1147
|
-
self.n_fee_hk_monitoring_thread = QThread(self)
|
|
1148
|
-
self.n_fee_hk_monitoring_worker = ProcessMonitoringWorker("egse.fee.n_fee_hk")
|
|
1149
|
-
self.n_fee_hk_monitoring_worker.moveToThread(self.n_fee_hk_monitoring_thread)
|
|
1150
|
-
self.n_fee_hk_monitoring_worker.is_running_signal.connect(self.on_n_fee_hk_is_running_signal)
|
|
1151
|
-
self.n_fee_hk_monitoring_thread.started.connect(self.n_fee_hk_monitoring_worker.start_process)
|
|
1152
|
-
self.n_fee_hk_monitoring_thread.start()
|
|
1153
|
-
|
|
1154
|
-
self.file_generation_monitoring_workers = {
|
|
1155
|
-
FILE_GENERATION_PROCESS_NAMES.FITSGEN: self.fitsgen_monitoring_worker,
|
|
1156
|
-
FILE_GENERATION_PROCESS_NAMES.FOV_HK: self.fov_hk_monitoring_worker,
|
|
1157
|
-
FILE_GENERATION_PROCESS_NAMES.N_FEE_HK: self.n_fee_hk_monitoring_worker
|
|
1158
|
-
}
|
|
1159
|
-
|
|
1160
|
-
def init_ui(self):
|
|
1161
|
-
""" Put the components in the GUI window.
|
|
1162
|
-
|
|
1163
|
-
The GUI comprises the following components:
|
|
1164
|
-
|
|
1165
|
-
- the toolbar;
|
|
1166
|
-
- on the left-hand side: one process widget per process;
|
|
1167
|
-
- on the right-hand side: one tab per process.
|
|
1168
|
-
"""
|
|
1169
|
-
|
|
1170
|
-
# Creating the content
|
|
1171
|
-
|
|
1172
|
-
app_frame = QFrame()
|
|
1173
|
-
app_frame.setObjectName("AppFrame")
|
|
1174
|
-
|
|
1175
|
-
self.create_toolbar()
|
|
1176
|
-
self.create_statusbar()
|
|
1177
|
-
|
|
1178
|
-
scroll = QScrollArea()
|
|
1179
|
-
# widget_frame = QFrame()
|
|
1180
|
-
|
|
1181
|
-
hbox = QHBoxLayout()
|
|
1182
|
-
vbox_left = QVBoxLayout()
|
|
1183
|
-
vbox_right = QVBoxLayout()
|
|
1184
|
-
hbox.addLayout(vbox_left)
|
|
1185
|
-
hbox.addLayout(vbox_right)
|
|
1186
|
-
|
|
1187
|
-
vbox_right.addStretch()
|
|
1188
|
-
|
|
1189
|
-
app_frame.setLayout(hbox)
|
|
1190
|
-
|
|
1191
|
-
# Obsid
|
|
1192
|
-
|
|
1193
|
-
info_gridbox = QGridLayout()
|
|
1194
|
-
|
|
1195
|
-
self.obsid = QLabel("No observation is running")
|
|
1196
|
-
self.setStyleSheet('QMainWindow{border: 3px solid green;}')
|
|
1197
|
-
info_gridbox.addWidget(QLabel("Obsid:"), 0, 0)
|
|
1198
|
-
info_gridbox.addWidget(self.obsid, 0, 1)
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
self.setup_id = QLabel("No setup loaded")
|
|
1202
|
-
info_gridbox.addWidget(QLabel("Setup ID:"), 1, 0)
|
|
1203
|
-
info_gridbox.addWidget(self.setup_id, 1, 1)
|
|
1204
|
-
|
|
1205
|
-
self.camera_id = QLabel("Camera ID unknown")
|
|
1206
|
-
info_gridbox.addWidget(QLabel("Camera ID:"), 2, 0)
|
|
1207
|
-
info_gridbox.addWidget(self.camera_id, 2, 1)
|
|
1208
|
-
|
|
1209
|
-
self.csl_hexapod_id = QLabel("Hexapod ID unknown")
|
|
1210
|
-
if "CSL" in SITE.ID:
|
|
1211
|
-
info_gridbox.addWidget(QLabel("Hexapod ID:"), 3, 0)
|
|
1212
|
-
info_gridbox.addWidget(self.csl_hexapod_id, 3, 1)
|
|
1213
|
-
|
|
1214
|
-
vbox_left.addLayout(info_gridbox)
|
|
1215
|
-
vbox_left.addWidget(QLabel())
|
|
1216
|
-
|
|
1217
|
-
self.overview_widget_device_cs_layout = QVBoxLayout()
|
|
1218
|
-
self.overview_widget_device_cs_layout.addStretch()
|
|
1219
|
-
self.overview_widget_device_cs = QGroupBox("Device Control Servers", self)
|
|
1220
|
-
self.overview_widget_device_cs.setLayout(self.overview_widget_device_cs_layout)
|
|
1221
|
-
self.overview_widget_device_cs.setToolTip(
|
|
1222
|
-
"EGSE device control servers:\n" +
|
|
1223
|
-
"can be started in this GUI or on the command line.")
|
|
1224
|
-
|
|
1225
|
-
self.overview_widget_non_device_cs_layout = QVBoxLayout()
|
|
1226
|
-
self.overview_widget_non_device_cs_layout.addStretch()
|
|
1227
|
-
self.overview_widget_non_device_cs = QGroupBox("Non-Device Control Servers", self)
|
|
1228
|
-
self.overview_widget_non_device_cs.setLayout(self.overview_widget_non_device_cs_layout)
|
|
1229
|
-
self.overview_widget_non_device_cs.setToolTip(
|
|
1230
|
-
"EGSE non-device control servers:\n" +
|
|
1231
|
-
"can be started in this GUI or on the command line (operational mode only).")
|
|
1232
|
-
|
|
1233
|
-
self.create_overview_widget_core()
|
|
1234
|
-
vbox_left.addWidget(self.overview_widget_core)
|
|
1235
|
-
|
|
1236
|
-
self.create_overview_widget_file_services()
|
|
1237
|
-
vbox_left.addWidget(self.overview_widget_file_services)
|
|
1238
|
-
|
|
1239
|
-
vbox_right.addWidget(self.overview_widget_device_cs)
|
|
1240
|
-
vbox_left.addWidget(self.overview_widget_non_device_cs)
|
|
1241
|
-
|
|
1242
|
-
scroll.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)
|
|
1243
|
-
scroll.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
|
1244
|
-
scroll.setWidgetResizable(True)
|
|
1245
|
-
|
|
1246
|
-
scroll.setWidget(app_frame)
|
|
1247
|
-
self.setCentralWidget(scroll)
|
|
1248
|
-
|
|
1249
|
-
def start_monitoring(self) -> object:
|
|
1250
|
-
""" Start listening on the monitoring port.
|
|
1251
|
-
|
|
1252
|
-
Create and start a thread that listens on the monitoring port in the background. If information is received
|
|
1253
|
-
before timeout, the Control Server is running: the light in the process tab should be set to green or orange,
|
|
1254
|
-
and the process information should be updated in the process tab.
|
|
1255
|
-
"""
|
|
1256
|
-
|
|
1257
|
-
for process_name, process_info in self.processes.items():
|
|
1258
|
-
|
|
1259
|
-
self.monitoring_threads[process_name] = QThread()
|
|
1260
|
-
|
|
1261
|
-
self.monitoring_workers[process_name] = MonitoringWorker(process_name, process_info)
|
|
1262
|
-
self.monitoring_workers[process_name].moveToThread(self.monitoring_threads[process_name])
|
|
1263
|
-
|
|
1264
|
-
# What to do when information has been sent back from the process thread?
|
|
1265
|
-
|
|
1266
|
-
self.monitoring_workers[process_name].process_status_signal.connect(self.on_process_status_signal)
|
|
1267
|
-
|
|
1268
|
-
self.monitoring_threads[process_name].started.connect(
|
|
1269
|
-
self.monitoring_workers[process_name].start_process)
|
|
1270
|
-
|
|
1271
|
-
self.monitoring_threads[process_name].start()
|
|
1272
|
-
|
|
1273
|
-
def on_setup_changed_signal(self, setup: Setup):
|
|
1274
|
-
""" Re-build the GUI after a change in setup.
|
|
1275
|
-
|
|
1276
|
-
Args:
|
|
1277
|
-
- setup: New setup.
|
|
1278
|
-
"""
|
|
1279
|
-
|
|
1280
|
-
# self.all_aeu_cs_button.disable()
|
|
1281
|
-
# self.start_aeu_button.setDisabled(True)
|
|
1282
|
-
# self.stop_aeu_button.setDisabled(True)
|
|
1283
|
-
|
|
1284
|
-
# Stop all workers and threads
|
|
1285
|
-
|
|
1286
|
-
for process_name in self.processes.keys():
|
|
1287
|
-
|
|
1288
|
-
self.monitoring_workers[process_name].process_status_signal.disconnect()
|
|
1289
|
-
|
|
1290
|
-
self.monitoring_workers[process_name].stop()
|
|
1291
|
-
self.monitoring_threads[process_name].quit()
|
|
1292
|
-
|
|
1293
|
-
for process_name in self.processes.keys():
|
|
1294
|
-
self.monitoring_threads[process_name].wait()
|
|
1295
|
-
|
|
1296
|
-
self.monitoring_workers.clear()
|
|
1297
|
-
self.monitoring_threads.clear()
|
|
1298
|
-
|
|
1299
|
-
# Make process list
|
|
1300
|
-
|
|
1301
|
-
self.processes.clear()
|
|
1302
|
-
self.core.clear()
|
|
1303
|
-
self.devices.clear()
|
|
1304
|
-
|
|
1305
|
-
self.start_aeu_button.setVisible(False)
|
|
1306
|
-
self.stop_aeu_button.setVisible(False)
|
|
1307
|
-
|
|
1308
|
-
# Remove the widgets from the layouts
|
|
1309
|
-
|
|
1310
|
-
while self.overview_widget_device_cs_layout.count():
|
|
1311
|
-
|
|
1312
|
-
widget = self.overview_widget_device_cs_layout.takeAt(0).widget()
|
|
1313
|
-
|
|
1314
|
-
if widget is not None:
|
|
1315
|
-
widget.deleteLater()
|
|
1316
|
-
|
|
1317
|
-
while self.overview_widget_non_device_cs_layout.count():
|
|
1318
|
-
|
|
1319
|
-
widget = self.overview_widget_non_device_cs_layout.takeAt(0).widget()
|
|
1320
|
-
|
|
1321
|
-
if widget is not None:
|
|
1322
|
-
widget.deleteLater()
|
|
1323
|
-
|
|
1324
|
-
self.process_widgets.clear()
|
|
1325
|
-
|
|
1326
|
-
# Re-build the process list
|
|
1327
|
-
|
|
1328
|
-
try:
|
|
1329
|
-
|
|
1330
|
-
with ProcessManagerProxy() as process_manager_proxy:
|
|
1331
|
-
|
|
1332
|
-
self.core = process_manager_proxy.get_core()
|
|
1333
|
-
self.devices = process_manager_proxy.get_devices()
|
|
1334
|
-
|
|
1335
|
-
self.processes.update(self.core)
|
|
1336
|
-
self.processes.update(self.devices)
|
|
1337
|
-
|
|
1338
|
-
except ConnectionError:
|
|
1339
|
-
|
|
1340
|
-
self.core = {}
|
|
1341
|
-
self.devices = {}
|
|
1342
|
-
|
|
1343
|
-
# Make new process widgets
|
|
1344
|
-
|
|
1345
|
-
for process_name in self.devices.keys():
|
|
1346
|
-
|
|
1347
|
-
process_widget = ProcessWidget(process_name, self.devices[process_name], self)
|
|
1348
|
-
|
|
1349
|
-
self.process_widgets[process_name] = process_widget
|
|
1350
|
-
|
|
1351
|
-
if process_widget.is_device:
|
|
1352
|
-
self.overview_widget_device_cs_layout.addWidget(process_widget)
|
|
1353
|
-
else:
|
|
1354
|
-
self.overview_widget_non_device_cs_layout.addWidget(process_widget)
|
|
1355
|
-
|
|
1356
|
-
self.process_widgets.update(self.process_widgets_core)
|
|
1357
|
-
|
|
1358
|
-
# Make sure the boxes stay nicely together when vertically resizing
|
|
1359
|
-
|
|
1360
|
-
self.overview_widget_device_cs_layout.addStretch()
|
|
1361
|
-
self.overview_widget_non_device_cs_layout.addStretch()
|
|
1362
|
-
|
|
1363
|
-
# Start monitoring the process status
|
|
1364
|
-
|
|
1365
|
-
self.start_monitoring()
|
|
1366
|
-
|
|
1367
|
-
if "AEU cRIO" in self.devices.keys():
|
|
1368
|
-
|
|
1369
|
-
# self.all_aeu_cs_button.set_selected(False)
|
|
1370
|
-
# self.all_aeu_cs_button.enable()
|
|
1371
|
-
self.start_aeu_button.setEnabled(True)
|
|
1372
|
-
self.stop_aeu_button.setEnabled(True)
|
|
1373
|
-
|
|
1374
|
-
else:
|
|
1375
|
-
|
|
1376
|
-
# self.all_aeu_cs_button.set_selected(False)
|
|
1377
|
-
# self.all_aeu_cs_button.disable()
|
|
1378
|
-
self.start_aeu_button.setEnabled(False)
|
|
1379
|
-
self.stop_aeu_button.setEnabled(False)
|
|
1380
|
-
|
|
1381
|
-
self.setup_id.setText(f"{setup.get_id()}")
|
|
1382
|
-
|
|
1383
|
-
try:
|
|
1384
|
-
cam_id = setup.camera.ID
|
|
1385
|
-
if cam_id != "EM":
|
|
1386
|
-
self.camera_id.setToolTip("Ah, beer! The cause of and the solution to all of life's problems!")
|
|
1387
|
-
self.camera_id.setText(cam_id)
|
|
1388
|
-
except AttributeError:
|
|
1389
|
-
self.camera_id.setText("Camera ID unknown")
|
|
1390
|
-
|
|
1391
|
-
try:
|
|
1392
|
-
self.csl_hexapod_id.setText(str(setup.gse.hexapod.ID))
|
|
1393
|
-
except AttributeError:
|
|
1394
|
-
self.csl_hexapod_id.setText("Hexapod ID unknown")
|
|
1395
|
-
|
|
1396
|
-
def on_obsid_changed_signal(self, obsid: ObservationIdentifier):
|
|
1397
|
-
""" Update the GUI for the new obsid.
|
|
1398
|
-
|
|
1399
|
-
Args:
|
|
1400
|
-
- obsid: The new obsid.
|
|
1401
|
-
"""
|
|
1402
|
-
|
|
1403
|
-
if obsid is None:
|
|
1404
|
-
|
|
1405
|
-
self.obsid.setText("No observation is running")
|
|
1406
|
-
self.setStyleSheet('QMainWindow{border: 3px solid green;}')
|
|
1407
|
-
|
|
1408
|
-
else:
|
|
1409
|
-
|
|
1410
|
-
self.obsid.setText(str(obsid))
|
|
1411
|
-
self.setStyleSheet('QMainWindow{border: 3px solid red;}')
|
|
1412
|
-
|
|
1413
|
-
def on_process_status_signal(self, process_info):
|
|
1414
|
-
""" Update the GUI for the process with the given name.
|
|
1415
|
-
|
|
1416
|
-
This method is called to update the GUI for the process with the given name in case the Control Server is
|
|
1417
|
-
running:
|
|
1418
|
-
|
|
1419
|
-
- the colour of the light in the process widget is set to green or orange;
|
|
1420
|
-
- the process information is updated in the tab.
|
|
1421
|
-
|
|
1422
|
-
The meaning of the colours is the following:
|
|
1423
|
-
|
|
1424
|
-
- green:
|
|
1425
|
-
- core process with running Control Server;
|
|
1426
|
-
- device process in simulator mode with running Control Server;
|
|
1427
|
-
- device process in operational mode with running Control Server and connection to the Controller;
|
|
1428
|
-
- orange: device process in operational mode with Control Server running but without connection to the
|
|
1429
|
-
Controller.
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
Args:
|
|
1433
|
-
process_info: Information for one process, to be updated in the
|
|
1434
|
-
Process Manager GUI.
|
|
1435
|
-
"""
|
|
1436
|
-
|
|
1437
|
-
process_name = process_info["Name"]
|
|
1438
|
-
color = process_info["Color"]
|
|
1439
|
-
|
|
1440
|
-
widget = self.process_widgets[process_name]
|
|
1441
|
-
|
|
1442
|
-
# Update the process widget
|
|
1443
|
-
|
|
1444
|
-
if "Simulator" in process_info:
|
|
1445
|
-
|
|
1446
|
-
if process_name != "DPU":
|
|
1447
|
-
|
|
1448
|
-
try:
|
|
1449
|
-
widget.sim_option_button.set_selected(process_info["Simulator"])
|
|
1450
|
-
except TypeError:
|
|
1451
|
-
# See #1419
|
|
1452
|
-
widget.sim_option_button.set_selected(False)
|
|
1453
|
-
LOGGER.debug(f"Unchecking the simulator checkbox in PM UI for {process_name}")
|
|
1454
|
-
|
|
1455
|
-
widget.sim_option_button.button_disabled = widget.sim_option_button.button_selected \
|
|
1456
|
-
if widget.sim_option_button.is_selected() \
|
|
1457
|
-
else widget.sim_option_button.button_disabled
|
|
1458
|
-
widget.sim_option_button.setDisabled(True)
|
|
1459
|
-
|
|
1460
|
-
widget.set_led_color(color)
|
|
1461
|
-
|
|
1462
|
-
if process_name == "Configuration Manager" and color == Indic.RED:
|
|
1463
|
-
|
|
1464
|
-
self.obsid.setText("Obsid unknown")
|
|
1465
|
-
self.setStyleSheet('QMainWindow{border: 3px solid orange;}')
|
|
1466
|
-
|
|
1467
|
-
def on_start_stop_cs_button_clicked(self, process_name):
|
|
1468
|
-
|
|
1469
|
-
self.monitoring_workers[process_name].start_stop_cs_button_clicked = True
|
|
1470
|
-
|
|
1471
|
-
def on_start_stop_non_cs_process_button_clicked(self, process_name):
|
|
1472
|
-
|
|
1473
|
-
self.file_generation_monitoring_workers[process_name].start_stop_cs_button_clicked = True
|
|
1474
|
-
|
|
1475
|
-
def on_logger_is_running_signal(self, logger_is_running: bool):
|
|
1476
|
-
|
|
1477
|
-
if logger_is_running:
|
|
1478
|
-
self.logger_widget.set_led_color(Indic.GREEN)
|
|
1479
|
-
else:
|
|
1480
|
-
self.logger_widget.set_led_color(Indic.RED)
|
|
1481
|
-
|
|
1482
|
-
def on_fitsgen_is_running_signal(self, fitsgen_is_running: bool):
|
|
1483
|
-
""" Update the icon of the toolbar button for FITS generation.
|
|
1484
|
-
|
|
1485
|
-
Args:
|
|
1486
|
-
- fitsgen_is_running: Indicates whether or not the FITS generation is running.
|
|
1487
|
-
"""
|
|
1488
|
-
|
|
1489
|
-
if fitsgen_is_running:
|
|
1490
|
-
self.fitsgen_widget.set_led_color(Indic.GREEN)
|
|
1491
|
-
else:
|
|
1492
|
-
self.fitsgen_widget.set_led_color(Indic.RED)
|
|
1493
|
-
|
|
1494
|
-
self.fitsgen_widget.start_stop_button.set_selected(not fitsgen_is_running)
|
|
1495
|
-
|
|
1496
|
-
def on_fov_hk_is_running_signal(self, fov_hk_is_running: bool):
|
|
1497
|
-
""" Update the icon of the toolbar button for the generation of FOV HK.
|
|
1498
|
-
|
|
1499
|
-
Args:
|
|
1500
|
-
- fov_hk_is_running: Indicates whether or not the generation of FOV HK is running.
|
|
1501
|
-
"""
|
|
1502
|
-
|
|
1503
|
-
if fov_hk_is_running:
|
|
1504
|
-
self.fov_hk_widget.set_led_color(Indic.GREEN)
|
|
1505
|
-
else:
|
|
1506
|
-
self.fov_hk_widget.set_led_color(Indic.RED)
|
|
1507
|
-
|
|
1508
|
-
self.fov_hk_widget.start_stop_button.set_selected(not fov_hk_is_running)
|
|
1509
|
-
|
|
1510
|
-
def on_n_fee_hk_is_running_signal(self, n_fee_hk_is_running: bool):
|
|
1511
|
-
""" Update the icon of the toolbar button for the generation of N-FEE HK.
|
|
1512
|
-
|
|
1513
|
-
Args:
|
|
1514
|
-
- n_fee_hk_is_running: Indicates whether or not the generation of N-FEE HK is running.
|
|
1515
|
-
"""
|
|
1516
|
-
|
|
1517
|
-
if n_fee_hk_is_running:
|
|
1518
|
-
self.n_fee_hk_widget.set_led_color(Indic.GREEN)
|
|
1519
|
-
else:
|
|
1520
|
-
self.n_fee_hk_widget.set_led_color(Indic.RED)
|
|
1521
|
-
|
|
1522
|
-
self.n_fee_hk_widget.start_stop_button.set_selected(not n_fee_hk_is_running)
|
|
1523
|
-
|
|
1524
|
-
def set_process_list(self):
|
|
1525
|
-
""" Make dictionary with all processes (core + devices).
|
|
1526
|
-
|
|
1527
|
-
The Configuration Manager is asked which processes (core + devices) are included in the setup.
|
|
1528
|
-
"""
|
|
1529
|
-
|
|
1530
|
-
self.processes = {}
|
|
1531
|
-
|
|
1532
|
-
# Ask the CM which CS are included in the setup
|
|
1533
|
-
|
|
1534
|
-
try:
|
|
1535
|
-
|
|
1536
|
-
with ProcessManagerProxy() as process_manager_proxy:
|
|
1537
|
-
|
|
1538
|
-
self.core = process_manager_proxy.get_core() # Core
|
|
1539
|
-
self.devices = process_manager_proxy.get_devices() # Devices
|
|
1540
|
-
|
|
1541
|
-
self.processes.update(self.core)
|
|
1542
|
-
self.processes.update(self.devices)
|
|
1543
|
-
|
|
1544
|
-
except ConnectionError:
|
|
1545
|
-
|
|
1546
|
-
self.devices = {}
|
|
1547
|
-
self.core = {}
|
|
1548
|
-
|
|
1549
|
-
def create_toolbar(self):
|
|
1550
|
-
""" Create the toolbar.
|
|
1551
|
-
|
|
1552
|
-
Buttons with the following functionality are foreseen:
|
|
1553
|
-
- Start/stop all EGSE device Control Servers in one go;
|
|
1554
|
-
- Start/stop all AEU Control Servers in one go:
|
|
1555
|
-
- Start/stop the FITS generation;
|
|
1556
|
-
- Start/stop the generation of FOV HK;
|
|
1557
|
-
- Start/stop the generation of N-FEE HK.
|
|
1558
|
-
"""
|
|
1559
|
-
|
|
1560
|
-
self.start_egse_button = ToggleButton(name="Start all device control servers in one go.",
|
|
1561
|
-
status_tip="Start all device control servers in one go.",
|
|
1562
|
-
selected=get_resource(":/icons/play-green.svg"),
|
|
1563
|
-
not_selected=get_resource(":/icons/play-green.svg")
|
|
1564
|
-
)
|
|
1565
|
-
self.start_egse_button.clicked.connect(self.start_egse)
|
|
1566
|
-
self.stop_egse_button = ToggleButton(name="Start all device control servers in one go.",
|
|
1567
|
-
status_tip="Stop all device control servers in one go.",
|
|
1568
|
-
selected=get_resource(":/icons/stop-red.svg"),
|
|
1569
|
-
not_selected=get_resource(":/icons/stop-red.svg")
|
|
1570
|
-
)
|
|
1571
|
-
self.stop_egse_button.clicked.connect(self.stop_egse)
|
|
1572
|
-
|
|
1573
|
-
self.start_aeu_button = ToggleButton(name="Start all AEU control servers in one go.",
|
|
1574
|
-
status_tip="Start all AEU control servers in one go.",
|
|
1575
|
-
selected=get_resource(":/icons/aeu-cs-start.svg"),
|
|
1576
|
-
not_selected=get_resource(":/icons/aeu-cs-start.svg"),
|
|
1577
|
-
disabled=[get_resource(":/icons/aeu-cs.svg"),
|
|
1578
|
-
get_resource(":/icons/aeu-cs.svg")]
|
|
1579
|
-
)
|
|
1580
|
-
self.start_aeu_button.clicked.connect(self.start_all_aeu_cs)
|
|
1581
|
-
|
|
1582
|
-
self.stop_aeu_button = ToggleButton(name="Stop all AEU control servers in one go.",
|
|
1583
|
-
status_tip="Stop all AEU control servers in one go.",
|
|
1584
|
-
selected=get_resource(":/icons/aeu-cs-stop.svg"),
|
|
1585
|
-
not_selected=get_resource(":/icons/aeu-cs-stop.svg"),
|
|
1586
|
-
disabled=get_resource(":/icons/aeu-cs.svg")
|
|
1587
|
-
)
|
|
1588
|
-
self.stop_aeu_button.clicked.connect(self.stop_all_aeu_cs)
|
|
1589
|
-
|
|
1590
|
-
th_ui_icon = QIcon(str(get_resource(":/icons/th_ui_logo.svg")))
|
|
1591
|
-
th_ui_action = QAction(th_ui_icon, f"Open the {SITE.ID} Operator UI", self)
|
|
1592
|
-
th_ui_action.setToolTip(f"Open the {SITE.ID} Operator UI")
|
|
1593
|
-
th_ui_action.setCheckable(False)
|
|
1594
|
-
th_ui_action.triggered.connect(open_th_ui)
|
|
1595
|
-
|
|
1596
|
-
fov_ui_icon = QIcon(str(get_resource(":/icons/location-marker.svg"))) # TODO
|
|
1597
|
-
fov_ui_action = QAction(fov_ui_icon, "Open the FOV UI", self)
|
|
1598
|
-
fov_ui_action.setToolTip("Open the FOV UI")
|
|
1599
|
-
fov_ui_action.setCheckable(False)
|
|
1600
|
-
fov_ui_action.triggered.connect(open_fov_ui)
|
|
1601
|
-
|
|
1602
|
-
visited_positions_ui_icon = QIcon(str(get_resource(":/icons/radar.svg"))) #TODO
|
|
1603
|
-
visited_positions_ui_action = QAction(visited_positions_ui_icon, "Open the visited-positions UI", self)
|
|
1604
|
-
visited_positions_ui_action.setToolTip("Open the visited-positions UI")
|
|
1605
|
-
visited_positions_ui_action.setCheckable(False)
|
|
1606
|
-
visited_positions_ui_action.triggered.connect(open_visited_positions_ui)
|
|
1607
|
-
|
|
1608
|
-
self.toolbar = self.addToolBar("MainToolbar")
|
|
1609
|
-
self.toolbar.addWidget(self.start_egse_button)
|
|
1610
|
-
self.toolbar.addWidget(self.stop_egse_button)
|
|
1611
|
-
self.toolbar.addSeparator()
|
|
1612
|
-
self.toolbar.addWidget(self.start_aeu_button)
|
|
1613
|
-
self.toolbar.addWidget(self.stop_aeu_button)
|
|
1614
|
-
|
|
1615
|
-
spacer = QWidget()
|
|
1616
|
-
spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
1617
|
-
self.toolbar.addWidget(spacer)
|
|
1618
|
-
|
|
1619
|
-
if "CSL" in SITE.ID:
|
|
1620
|
-
self.toolbar.addAction(fov_ui_action)
|
|
1621
|
-
|
|
1622
|
-
self.toolbar.addAction(th_ui_action)
|
|
1623
|
-
self.toolbar.addSeparator()
|
|
1624
|
-
|
|
1625
|
-
self.toolbar.addAction(visited_positions_ui_action)
|
|
1626
|
-
|
|
1627
|
-
return self.toolbar
|
|
1628
|
-
|
|
1629
|
-
def create_statusbar(self):
|
|
1630
|
-
""" Create the status bar."""
|
|
1631
|
-
|
|
1632
|
-
self.statusBar().setStyleSheet("border: 0; background-color: #FFF8DC;")
|
|
1633
|
-
self.statusBar().setStyleSheet("QStatusBar::item {border: none;}")
|
|
1634
|
-
# self.statusBar().addPermanentWidget(VLine())
|
|
1635
|
-
|
|
1636
|
-
def start_egse(self):
|
|
1637
|
-
""" Start all EGSE device Control Servers in one go.
|
|
1638
|
-
|
|
1639
|
-
We only try to start the control servers that are currently down. For those, the following steps are taken:
|
|
1640
|
-
- The start/stop button of each of these control servers should show the stop icon;
|
|
1641
|
-
- The simulator option button is disabled;
|
|
1642
|
-
- The control server is started, in the mode indicated by the simulator option button.
|
|
1643
|
-
|
|
1644
|
-
For the control servers that could be started, the start/stop button keeps showing the stop icon and the
|
|
1645
|
-
simulator mode button stays disabled. For control servers that could not be started, the start/stop button
|
|
1646
|
-
show the start icon again and the simulator mode button is enabled again.
|
|
1647
|
-
"""
|
|
1648
|
-
|
|
1649
|
-
LOGGER.info(f"Starting all device Control Servers")
|
|
1650
|
-
thread = threading.Thread(target=self._start_egse)
|
|
1651
|
-
|
|
1652
|
-
thread.daemon = True
|
|
1653
|
-
thread.start()
|
|
1654
|
-
|
|
1655
|
-
def _start_egse(self):
|
|
1656
|
-
|
|
1657
|
-
# First make sure that the start/stop buttons in the process widgets show the hourglass icon (denoting is going
|
|
1658
|
-
# on with that CD) and that the simulator option button is disabled (so you cannot switch between simulator and
|
|
1659
|
-
# operational mode while starting the CS)
|
|
1660
|
-
|
|
1661
|
-
for process_name in self.devices.keys():
|
|
1662
|
-
|
|
1663
|
-
process_widget: ProcessWidget = self.process_widgets[process_name]
|
|
1664
|
-
|
|
1665
|
-
if process_widget.status_led.color == Indic.RED:
|
|
1666
|
-
|
|
1667
|
-
process_widget.start_stop_button.setDisabled(True)
|
|
1668
|
-
process_widget.sim_option_button.setEnabled(False)
|
|
1669
|
-
|
|
1670
|
-
# In order not to overload the Process Manager, we loop through the list of devices again and start the CS
|
|
1671
|
-
# one-by-one
|
|
1672
|
-
|
|
1673
|
-
with ProcessManagerProxy() as pm:
|
|
1674
|
-
|
|
1675
|
-
for process_name in self.devices.keys():
|
|
1676
|
-
|
|
1677
|
-
if process_widget.status_led.color == Indic.RED:
|
|
1678
|
-
|
|
1679
|
-
self.monitoring_workers[process_name].start_stop_cs_button_clicked = True
|
|
1680
|
-
|
|
1681
|
-
sim_mode = self.process_widgets[process_name].is_simulator_mode
|
|
1682
|
-
response: Response = pm.start_cs(process_name, sim_mode)
|
|
1683
|
-
|
|
1684
|
-
if not response.successful:
|
|
1685
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m",
|
|
1686
|
-
"egse.procman.cannot_start_process_popup", "--process_name",
|
|
1687
|
-
process_name, "--message", response.message])
|
|
1688
|
-
gui_process.execute(detach_from_parent=True)
|
|
1689
|
-
|
|
1690
|
-
def stop_egse(self):
|
|
1691
|
-
""" Shut down all EGSE device Control Servers in one go.
|
|
1692
|
-
|
|
1693
|
-
We only try to start the control servers that are currently running. For those, the following steps are taken:
|
|
1694
|
-
- The start/stop button of each of these control servers should show the start icon;
|
|
1695
|
-
- The simulator option button is disabled;
|
|
1696
|
-
- The control server is stopped.
|
|
1697
|
-
|
|
1698
|
-
For the control servers that could be stopped, the start/stop button keeps showing the start icon and the
|
|
1699
|
-
simulator mode button is enabled. For control servers that could not be stopped, the start/stop button
|
|
1700
|
-
show the stop icon again and the simulator mode button is disabled again.
|
|
1701
|
-
"""
|
|
1702
|
-
|
|
1703
|
-
LOGGER.info(f"Shutting down all device Control Servers")
|
|
1704
|
-
thread = threading.Thread(target=self._stop_egse)
|
|
1705
|
-
|
|
1706
|
-
thread.daemon = True
|
|
1707
|
-
thread.start()
|
|
1708
|
-
|
|
1709
|
-
def _stop_egse(self):
|
|
1710
|
-
|
|
1711
|
-
# First make sure that the start/stop buttons in the process widgets show the hourglass icon (denoting is going
|
|
1712
|
-
# on with that CD) and that the simulator option button is disabled (so you cannot switch between simulator and
|
|
1713
|
-
# operational mode while starting the CS)
|
|
1714
|
-
|
|
1715
|
-
for process_name in self.devices.keys():
|
|
1716
|
-
|
|
1717
|
-
process_widget: ProcessWidget = self.process_widgets[process_name]
|
|
1718
|
-
|
|
1719
|
-
if process_widget.status_led.color != Indic.RED:
|
|
1720
|
-
|
|
1721
|
-
process_widget.start_stop_button.setDisabled(True)
|
|
1722
|
-
|
|
1723
|
-
# In order not to overload the Process Manager, we loop through the list of devices again and start the CS
|
|
1724
|
-
# one-by-one
|
|
1725
|
-
|
|
1726
|
-
with ProcessManagerProxy() as pm:
|
|
1727
|
-
|
|
1728
|
-
for process_name in reversed(self.devices.keys()):
|
|
1729
|
-
|
|
1730
|
-
if process_widget.status_led.color != Indic.RED:
|
|
1731
|
-
|
|
1732
|
-
self.monitoring_workers[process_name].start_stop_cs_button_clicked = True
|
|
1733
|
-
pm.shut_down_cs(process_name)
|
|
1734
|
-
|
|
1735
|
-
def start_all_aeu_cs(self):
|
|
1736
|
-
""" Start the AEU Control Servers in one go."""
|
|
1737
|
-
|
|
1738
|
-
thread = threading.Thread(target=self._start_all_aeu_cs)
|
|
1739
|
-
|
|
1740
|
-
thread.daemon = True
|
|
1741
|
-
thread.start()
|
|
1742
|
-
|
|
1743
|
-
def _start_all_aeu_cs(self):
|
|
1744
|
-
|
|
1745
|
-
# First make sure that the start/stop buttons in the process widgets show the hourglass icon (denoting is going
|
|
1746
|
-
# on with that CD) and that the simulator option button is disabled (so you cannot switch between simulator and
|
|
1747
|
-
# operational mode while starting the CS)
|
|
1748
|
-
|
|
1749
|
-
for process_name in self.devices.keys():
|
|
1750
|
-
|
|
1751
|
-
if str.startswith(process_name, "AEU"):
|
|
1752
|
-
|
|
1753
|
-
process_widget: ProcessWidget = self.process_widgets[process_name]
|
|
1754
|
-
|
|
1755
|
-
if process_widget.status_led.color == Indic.RED:
|
|
1756
|
-
|
|
1757
|
-
process_widget.start_stop_button.setDisabled(True)
|
|
1758
|
-
process_widget.sim_option_button.setEnabled(False)
|
|
1759
|
-
|
|
1760
|
-
# In order not to overload the Process Manager, we loop through the list of devices again and start the CS
|
|
1761
|
-
# one-by-one
|
|
1762
|
-
|
|
1763
|
-
with ProcessManagerProxy() as pm:
|
|
1764
|
-
|
|
1765
|
-
for process_name in self.devices.keys():
|
|
1766
|
-
|
|
1767
|
-
if str.startswith(process_name, "AEU"):
|
|
1768
|
-
|
|
1769
|
-
process_widget: ProcessWidget = self.process_widgets[process_name]
|
|
1770
|
-
|
|
1771
|
-
if process_widget.status_led.color == Indic.RED:
|
|
1772
|
-
|
|
1773
|
-
self.monitoring_workers[process_name].start_stop_cs_button_clicked = True
|
|
1774
|
-
|
|
1775
|
-
sim_mode = self.process_widgets[process_name].is_simulator_mode
|
|
1776
|
-
response: Response = pm.start_cs(process_name, sim_mode)
|
|
1777
|
-
|
|
1778
|
-
if not response.successful:
|
|
1779
|
-
gui_process = SubProcess("MyApp", [sys.executable, "-m",
|
|
1780
|
-
"egse.procman.cannot_start_process_popup",
|
|
1781
|
-
"--process_name", process_name,
|
|
1782
|
-
"--message", response.message])
|
|
1783
|
-
gui_process.execute(detach_from_parent=True)
|
|
1784
|
-
|
|
1785
|
-
def stop_all_aeu_cs(self):
|
|
1786
|
-
""" Shut down the AEU Control Servers in one go."""
|
|
1787
|
-
|
|
1788
|
-
thread = threading.Thread(target=self._stop_all_aeu_cs)
|
|
1789
|
-
|
|
1790
|
-
thread.daemon = True
|
|
1791
|
-
thread.start()
|
|
1792
|
-
|
|
1793
|
-
def _stop_all_aeu_cs(self):
|
|
1794
|
-
|
|
1795
|
-
# First make sure that the start/stop buttons in the process widgets show the hourglass icon (denoting is going
|
|
1796
|
-
# on with that CD) and that the simulator option button is disabled (so you cannot switch between simulator and
|
|
1797
|
-
# operational mode while starting the CS)
|
|
1798
|
-
|
|
1799
|
-
for process_name in self.devices.keys():
|
|
1800
|
-
|
|
1801
|
-
if str.startswith(process_name, "AEU"):
|
|
1802
|
-
|
|
1803
|
-
process_widget: ProcessWidget = self.process_widgets[process_name]
|
|
1804
|
-
|
|
1805
|
-
if process_widget.status_led.color != Indic.RED:
|
|
1806
|
-
process_widget.start_stop_button.setDisabled(True)
|
|
1807
|
-
|
|
1808
|
-
# In order not to overload the Process Manager, we loop through the list of devices again and start the CS
|
|
1809
|
-
# one-by-one
|
|
1810
|
-
|
|
1811
|
-
with ProcessManagerProxy() as pm:
|
|
1812
|
-
|
|
1813
|
-
for process_name in reversed(self.devices.keys()):
|
|
1814
|
-
|
|
1815
|
-
if str.startswith(process_name, "AEU"):
|
|
1816
|
-
|
|
1817
|
-
process_widget: ProcessWidget = self.process_widgets[process_name]
|
|
1818
|
-
|
|
1819
|
-
if process_widget.status_led.color != Indic.RED:
|
|
1820
|
-
|
|
1821
|
-
self.monitoring_workers[process_name].start_stop_cs_button_clicked = True
|
|
1822
|
-
pm.shut_down_cs(process_name)
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
# def start_stop_fitsgen(self):
|
|
1826
|
-
# """ Start/stop the FITS generation.
|
|
1827
|
-
#
|
|
1828
|
-
# Depending on the selection state of the FITS generation button, the FITS generation will be started or stopped
|
|
1829
|
-
# (this is done in a separate thread).
|
|
1830
|
-
# """
|
|
1831
|
-
#
|
|
1832
|
-
# if self.fitsgen_button.is_selected():
|
|
1833
|
-
# thread = threading.Thread(target=stop_fitsgen)
|
|
1834
|
-
# else:
|
|
1835
|
-
# thread = threading.Thread(target=start_fitsgen)
|
|
1836
|
-
#
|
|
1837
|
-
# thread.daemon = True
|
|
1838
|
-
# thread.start()
|
|
1839
|
-
#
|
|
1840
|
-
# def start_stop_fov_hk(self):
|
|
1841
|
-
# """ Start/stop the generation of FOV HK.
|
|
1842
|
-
#
|
|
1843
|
-
# Depending on the selection state of the FOV HK generation button, the FOV HK generation will be started or
|
|
1844
|
-
# stopped (this is done in a separate thread).
|
|
1845
|
-
# """
|
|
1846
|
-
#
|
|
1847
|
-
# if self.fov_hk_button.is_selected():
|
|
1848
|
-
# thread = threading.Thread(target=stop_fov_hk)
|
|
1849
|
-
# else:
|
|
1850
|
-
# thread = threading.Thread(target=start_fov_hk)
|
|
1851
|
-
#
|
|
1852
|
-
# thread.daemon = True
|
|
1853
|
-
# thread.start()
|
|
1854
|
-
#
|
|
1855
|
-
# def start_stop_n_fee_hk(self):
|
|
1856
|
-
# """ Start/stop the generation of N-FEE HK.
|
|
1857
|
-
#
|
|
1858
|
-
# Depending on the selection state of the N-FEE HK generation button, the N-FEE HK generation will be started or
|
|
1859
|
-
# stopped (this is done in a separate thread).
|
|
1860
|
-
# """
|
|
1861
|
-
#
|
|
1862
|
-
# if self.n_fee_hk_button.is_selected():
|
|
1863
|
-
# thread = threading.Thread(target=stop_n_fee_hk)
|
|
1864
|
-
# else:
|
|
1865
|
-
# thread = threading.Thread(target=start_n_fee_hk)
|
|
1866
|
-
#
|
|
1867
|
-
# thread.daemon = True
|
|
1868
|
-
# thread.start()
|
|
1869
|
-
|
|
1870
|
-
def create_overview_widget_core(self):
|
|
1871
|
-
""" Create a frame with one process widget per core process."""
|
|
1872
|
-
|
|
1873
|
-
# Core processes
|
|
1874
|
-
|
|
1875
|
-
self.overview_widget_core_layout = QVBoxLayout()
|
|
1876
|
-
|
|
1877
|
-
for process_name in self.core.keys():
|
|
1878
|
-
|
|
1879
|
-
process_widget = ProcessWidget(
|
|
1880
|
-
process_name, self.core[process_name], self,
|
|
1881
|
-
include_start_stop_button=False)
|
|
1882
|
-
self.process_widgets[process_name] = process_widget
|
|
1883
|
-
self.process_widgets_core[process_name] = process_widget
|
|
1884
|
-
|
|
1885
|
-
self.overview_widget_core_layout.addWidget(process_widget)
|
|
1886
|
-
|
|
1887
|
-
self.logger_widget = LogWidget(self)
|
|
1888
|
-
self.overview_widget_core_layout.addWidget(self.logger_widget)
|
|
1889
|
-
|
|
1890
|
-
self.overview_widget_core = QGroupBox("Services/Core", self)
|
|
1891
|
-
self.overview_widget_core.setLayout(self.overview_widget_core_layout)
|
|
1892
|
-
self.overview_widget_core.setToolTip(
|
|
1893
|
-
"EGSE core processes: must be running at all times.")
|
|
1894
|
-
|
|
1895
|
-
def create_overview_widget_file_services(self):
|
|
1896
|
-
|
|
1897
|
-
# File generation processes
|
|
1898
|
-
|
|
1899
|
-
self.overview_widget_file_services_layout = QVBoxLayout()
|
|
1900
|
-
|
|
1901
|
-
self.fitsgen_widget = FitsgenWidget(self)
|
|
1902
|
-
self.overview_widget_file_services_layout.addWidget(self.fitsgen_widget)
|
|
1903
|
-
|
|
1904
|
-
self.fov_hk_widget = FovHkWidget(self)
|
|
1905
|
-
self.overview_widget_file_services_layout.addWidget(self.fov_hk_widget)
|
|
1906
|
-
|
|
1907
|
-
self.n_fee_hk_widget = NFeeHkWidget(self)
|
|
1908
|
-
self.overview_widget_file_services_layout.addWidget(self.n_fee_hk_widget)
|
|
1909
|
-
|
|
1910
|
-
self.overview_widget_file_services = QGroupBox("File Generation Processes", self)
|
|
1911
|
-
self.overview_widget_file_services.setLayout(self.overview_widget_file_services_layout)
|
|
1912
|
-
# self.overview_widget_file_services.setToolTip(
|
|
1913
|
-
# "EGSE core processes: must be running at all times.")
|
|
1914
|
-
|
|
1915
|
-
def closeEvent(self, close_event: QCloseEvent) -> None:
|
|
1916
|
-
""" Make sure that all threads are stopped when the GUI is closed.
|
|
1917
|
-
|
|
1918
|
-
Args:
|
|
1919
|
-
- close_event: Close event received when the GUI is closed.
|
|
1920
|
-
"""
|
|
1921
|
-
for monitoring_worker in self.monitoring_workers.values():
|
|
1922
|
-
monitoring_worker.active = False
|
|
1923
|
-
|
|
1924
|
-
for monitoring_thread in self.monitoring_threads.values():
|
|
1925
|
-
monitoring_thread.quit()
|
|
1926
|
-
|
|
1927
|
-
self.setup_monitoring_worker.active = False
|
|
1928
|
-
self.setup_monitoring_thread.quit()
|
|
1929
|
-
|
|
1930
|
-
self.logger_monitoring_worker.active = False
|
|
1931
|
-
self.logger_monitoring_thread.quit()
|
|
1932
|
-
|
|
1933
|
-
self.fitsgen_monitoring_worker.active = False
|
|
1934
|
-
self.fitsgen_monitoring_thread.quit()
|
|
1935
|
-
|
|
1936
|
-
self.fov_hk_monitoring_worker.active = False
|
|
1937
|
-
self.fov_hk_monitoring_thread.quit()
|
|
1938
|
-
|
|
1939
|
-
self.n_fee_hk_monitoring_worker.active = False
|
|
1940
|
-
self.n_fee_hk_monitoring_thread.quit()
|
|
1941
|
-
|
|
1942
|
-
# Group the waiting
|
|
1943
|
-
for monitoring_thread in self.monitoring_threads.values():
|
|
1944
|
-
monitoring_thread.wait()
|
|
1945
|
-
|
|
1946
|
-
self.setup_monitoring_thread.wait()
|
|
1947
|
-
self.logger_monitoring_thread.wait()
|
|
1948
|
-
self.fitsgen_monitoring_thread.wait()
|
|
1949
|
-
self.fov_hk_monitoring_thread.wait()
|
|
1950
|
-
self.n_fee_hk_monitoring_thread.wait()
|
|
1951
|
-
|
|
1952
|
-
class ProcessManagerUIModel:
|
|
1953
|
-
|
|
1954
|
-
def __init__(self):
|
|
1955
|
-
""" Initialisation of the Process Manager UI model."""
|
|
1956
|
-
|
|
1957
|
-
try:
|
|
1958
|
-
|
|
1959
|
-
self.process_manager = ProcessManagerProxy()
|
|
1960
|
-
|
|
1961
|
-
except ConnectionError:
|
|
1962
|
-
|
|
1963
|
-
self.process_manager = None
|
|
1964
|
-
|
|
1965
|
-
def is_connected(self):
|
|
1966
|
-
""" Checks whether the Process Manager Control Server is active.
|
|
1967
|
-
|
|
1968
|
-
Checks whether a connection to the Process Manager Control Server has been established.
|
|
1969
|
-
|
|
1970
|
-
Returns:
|
|
1971
|
-
- True if a connection to the Process Manager Control Server has been established; False otherwise.
|
|
1972
|
-
"""
|
|
1973
|
-
|
|
1974
|
-
return self.process_manager.ping() and self.process_manager.is_cs_connected()
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
class ProcessManagerUIController:
|
|
1978
|
-
|
|
1979
|
-
def __init__(self, model: ProcessManagerUIModel, view: ProcessManagerUIView):
|
|
1980
|
-
""" Initialisation of the Controller for the Process Manager GUI.
|
|
1981
|
-
|
|
1982
|
-
Args:
|
|
1983
|
-
- model: Process Manager UI model.
|
|
1984
|
-
- view: Process Manager UI view.
|
|
1985
|
-
"""
|
|
1986
|
-
|
|
1987
|
-
self.model = model
|
|
1988
|
-
self.view = view
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
def main():
|
|
1992
|
-
""" Main method to launch the Process Manager GUI."""
|
|
1993
|
-
lock_file = QLockFile(str(Path("~/pm_ui.app.lock").expanduser()))
|
|
1994
|
-
|
|
1995
|
-
multiprocessing.current_process().name = "pm_ui"
|
|
1996
|
-
app = QApplication(sys.argv)
|
|
1997
|
-
app.setWindowIcon(QIcon(str(get_resource(":/icons/pm_ui.svg"))))
|
|
1998
|
-
|
|
1999
|
-
if lock_file.tryLock(100):
|
|
2000
|
-
process_status = ProcessStatus()
|
|
2001
|
-
|
|
2002
|
-
timer_thread = threading.Thread(target=do_every, args=(10, process_status.update))
|
|
2003
|
-
timer_thread.daemon = True
|
|
2004
|
-
timer_thread.start()
|
|
2005
|
-
|
|
2006
|
-
start_http_server(GUI_SETTINGS.METRICS_PORT)
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
# Check whether the Process Manager CS is running
|
|
2010
|
-
# (show a warning in a pop-up window if it's not)
|
|
2011
|
-
|
|
2012
|
-
try:
|
|
2013
|
-
|
|
2014
|
-
with ProcessManagerProxy():
|
|
2015
|
-
|
|
2016
|
-
if not is_configuration_manager_active():
|
|
2017
|
-
|
|
2018
|
-
description = "Could not connect to Configuration Manager"
|
|
2019
|
-
into_text = (
|
|
2020
|
-
"The GUI will start, but without listed processes. "
|
|
2021
|
-
"Please, check if the Configuration Manager is running and start the server if needed."
|
|
2022
|
-
# "Otherwise, check if the correct HOSTNAME for the Configuration Manager is set in the "
|
|
2023
|
-
# "Settings.yaml "
|
|
2024
|
-
# "configuration file."
|
|
2025
|
-
"The Process Manager GUI will have to be re-started after that."
|
|
2026
|
-
)
|
|
2027
|
-
|
|
2028
|
-
show_info_message(description, into_text)
|
|
2029
|
-
|
|
2030
|
-
except ConnectionError:
|
|
2031
|
-
|
|
2032
|
-
description = "Could not connect to Process Manager Control Server"
|
|
2033
|
-
|
|
2034
|
-
into_text = (
|
|
2035
|
-
"The GUI will start, but the connection button will show a disconnected state. "
|
|
2036
|
-
"Please, check if the Control Server is running and start the server if needed. "
|
|
2037
|
-
"Otherwise, check if the correct HOSTNAME for the control server is set in the "
|
|
2038
|
-
"Settings.yaml "
|
|
2039
|
-
"configuration file."
|
|
2040
|
-
)
|
|
2041
|
-
|
|
2042
|
-
show_info_message(description, into_text)
|
|
2043
|
-
|
|
2044
|
-
# proxy = ProcessManagerProxy()
|
|
2045
|
-
|
|
2046
|
-
# if not proxy.ping():
|
|
2047
|
-
# description = "Could not connect to Process Manager Control Server"
|
|
2048
|
-
# into_text = (
|
|
2049
|
-
# "The GUI will start, but the connection button will show a disconnected state. "
|
|
2050
|
-
# "Please check if the Control Server is running and start the server if needed. "
|
|
2051
|
-
# "Otherwise, check if the correct HOSTNAME for the control server is set in the "
|
|
2052
|
-
# "Settings.yaml "
|
|
2053
|
-
# "configuration file."
|
|
2054
|
-
# )
|
|
2055
|
-
|
|
2056
|
-
# show_info_message(description, into_text)
|
|
2057
|
-
|
|
2058
|
-
# proxy.disconnect_cs()
|
|
2059
|
-
|
|
2060
|
-
# Create the Process Manager GUI, following the MVC-model
|
|
2061
|
-
|
|
2062
|
-
view = ProcessManagerUIView()
|
|
2063
|
-
model = ProcessManagerUIModel()
|
|
2064
|
-
ProcessManagerUIController(model, view)
|
|
2065
|
-
|
|
2066
|
-
view.show()
|
|
2067
|
-
|
|
2068
|
-
return app.exec_()
|
|
2069
|
-
else:
|
|
2070
|
-
error_message = QMessageBox()
|
|
2071
|
-
error_message.setIcon(QMessageBox.Warning)
|
|
2072
|
-
error_message.setWindowTitle("Error")
|
|
2073
|
-
error_message.setText("The Process Manager (PM) GUI application is already running!")
|
|
2074
|
-
error_message.setStandardButtons(QMessageBox.Ok)
|
|
2075
|
-
|
|
2076
|
-
return error_message.exec()
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
if __name__ == '__main__':
|
|
2080
|
-
|
|
2081
|
-
sys.exit(main())
|