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/gimbal/symetrie/pmac.py
DELETED
|
@@ -1,1006 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
PMAC Interface to Gimbal Hardware Controller from Symétrie.
|
|
3
|
-
|
|
4
|
-
Some of the code below is based on the dls_pmaclib Python library that was made available
|
|
5
|
-
as open source by Diamond Control under the LGPL v3.x. For more info and the original
|
|
6
|
-
source code, please go to http://controls.diamond.ac.uk/downloads/python/index.php].
|
|
7
|
-
|
|
8
|
-
Author: Rik Huygen
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
import logging
|
|
12
|
-
import socket
|
|
13
|
-
import struct
|
|
14
|
-
import threading
|
|
15
|
-
from datetime import datetime
|
|
16
|
-
from datetime import timedelta
|
|
17
|
-
from typing import List
|
|
18
|
-
|
|
19
|
-
from egse.gimbal.symetrie.pmac_regex import match_float_response
|
|
20
|
-
from egse.gimbal.symetrie.pmac_regex import match_int_response
|
|
21
|
-
from egse.gimbal.symetrie.pmac_regex import match_string_response
|
|
22
|
-
|
|
23
|
-
logger = logging.getLogger(__name__)
|
|
24
|
-
|
|
25
|
-
# Command set Request
|
|
26
|
-
|
|
27
|
-
VR_PMAC_SENDLINE = 0xB0
|
|
28
|
-
VR_PMAC_GETLINE = 0xB1
|
|
29
|
-
VR_PMAC_FLUSH = 0xB3
|
|
30
|
-
VR_PMAC_GETMEM = 0xB4
|
|
31
|
-
VR_PMAC_SETMEM = 0xB5
|
|
32
|
-
VR_PMAC_SETBIT = 0xBA
|
|
33
|
-
VR_PMAC_SETBITS = 0xBB
|
|
34
|
-
VR_PMAC_PORT = 0xBE
|
|
35
|
-
VR_PMAC_GETRESPONSE = 0xBF
|
|
36
|
-
VR_PMAC_READREADY = 0xC2
|
|
37
|
-
VR_CTRL_RESPONSE = 0xC4
|
|
38
|
-
VR_PMAC_GETBUFFER = 0xC5
|
|
39
|
-
VR_PMAC_WRITEBUFFER = 0xC6
|
|
40
|
-
VR_PMAC_WRITEERROR = 0xC7
|
|
41
|
-
VR_FWDOWNLOAD = 0xCB
|
|
42
|
-
VR_IPADDRESS = 0xE0
|
|
43
|
-
|
|
44
|
-
# Request Types
|
|
45
|
-
|
|
46
|
-
VR_DOWNLOAD = 0x40 # Command send to the device
|
|
47
|
-
VR_UPLOAD = 0xC0 # Command send to host
|
|
48
|
-
|
|
49
|
-
# API Function Error Codes
|
|
50
|
-
|
|
51
|
-
ERR_DISCONNECTED = -1
|
|
52
|
-
ERR_NOT_READY_2_BE_READ = -2
|
|
53
|
-
ERR_NO_CMD_MATCHING = -3
|
|
54
|
-
ERR_WRITE = -4
|
|
55
|
-
ERR_READ = -5
|
|
56
|
-
ERR_CONNECTION = -6
|
|
57
|
-
ERR_CMD_TIMEOUT = -7
|
|
58
|
-
|
|
59
|
-
# API Returns
|
|
60
|
-
|
|
61
|
-
RETURN_SUCCESS = 0
|
|
62
|
-
RETURN_IGNORED = -1
|
|
63
|
-
RETURN_FAILURE = -2
|
|
64
|
-
|
|
65
|
-
# The States of Q20 which are checked after the command has executed.
|
|
66
|
-
|
|
67
|
-
Q20_0: List[int] = [] # no checking of Q20 to be done
|
|
68
|
-
Q20_1: List[int] = [RETURN_SUCCESS] # wait until success
|
|
69
|
-
Q20_2: List[int] = [RETURN_SUCCESS, RETURN_IGNORED]
|
|
70
|
-
Q20_3: List[int] = [RETURN_SUCCESS, RETURN_IGNORED, RETURN_FAILURE]
|
|
71
|
-
|
|
72
|
-
# Each command is defined as a dictionary with the following structure:
|
|
73
|
-
#
|
|
74
|
-
# {
|
|
75
|
-
# 'name' : [string] Human readable name of the command
|
|
76
|
-
# 'cmd' : [string] Actual command string for the controller.
|
|
77
|
-
# Can contain format replacement fields for commands that take input values.
|
|
78
|
-
# 'in' : [int] Number of input values. This should match up with the number of replacement fields in 'cmd'
|
|
79
|
-
# 'out' : [type] Number of output variable. The type of the output variables is defined by 'out_type'
|
|
80
|
-
# 'return' : [string] The command to retreive and check the output.
|
|
81
|
-
# 'check' : [iterable] Iterable containing the output values that are expected.
|
|
82
|
-
# 'out_type': [function] A function object that is used to convert the output variables from string to <type func>.
|
|
83
|
-
# }
|
|
84
|
-
#
|
|
85
|
-
#
|
|
86
|
-
|
|
87
|
-
CMD_STOP = {
|
|
88
|
-
"name": "STOP",
|
|
89
|
-
"cmd": "&2 Q20=2",
|
|
90
|
-
"in": 0,
|
|
91
|
-
"out": 0,
|
|
92
|
-
"return": "&2 Q20",
|
|
93
|
-
"check": Q20_1,
|
|
94
|
-
"out_type": None,
|
|
95
|
-
}
|
|
96
|
-
CMD_HOMING = {
|
|
97
|
-
"name": "HOMING",
|
|
98
|
-
"cmd": "&2 Q20=1",
|
|
99
|
-
"in": 0,
|
|
100
|
-
"out": 0,
|
|
101
|
-
"return": "&2 Q20",
|
|
102
|
-
"check": Q20_1,
|
|
103
|
-
"out_type": None,
|
|
104
|
-
}
|
|
105
|
-
CMD_CONTROLON = {
|
|
106
|
-
"name": "CONTROL_ON",
|
|
107
|
-
"cmd": "&2 Q20=3",
|
|
108
|
-
"in": 0,
|
|
109
|
-
"out": 0,
|
|
110
|
-
"return": "&2 Q20",
|
|
111
|
-
"check": Q20_3,
|
|
112
|
-
"out_type": None,
|
|
113
|
-
}
|
|
114
|
-
CMD_CONTROLOFF = {
|
|
115
|
-
"name": "CONTROL_OFF",
|
|
116
|
-
"cmd": "&2 Q20=4",
|
|
117
|
-
"in": 0,
|
|
118
|
-
"out": 0,
|
|
119
|
-
"return": "&2 Q20",
|
|
120
|
-
"check": Q20_1,
|
|
121
|
-
"out_type": None,
|
|
122
|
-
}
|
|
123
|
-
CMD_MOVE = {
|
|
124
|
-
"name": "MOVE",
|
|
125
|
-
"cmd": "&2 Q70={cm} Q71={grx:.6f} Q72={gry:.6f} Q20=11",
|
|
126
|
-
"in": 3,
|
|
127
|
-
"out": 0,
|
|
128
|
-
"return": "&2 Q20",
|
|
129
|
-
"check": Q20_3,
|
|
130
|
-
"out_type": None,
|
|
131
|
-
}
|
|
132
|
-
CMD_MAINTENANCE = {
|
|
133
|
-
"name": "MAINTENANCE",
|
|
134
|
-
"cmd": "&2 Q80={axis} Q20=12",
|
|
135
|
-
"in": 1,
|
|
136
|
-
"out": 0,
|
|
137
|
-
"return": "&2 Q20",
|
|
138
|
-
"check": Q20_2,
|
|
139
|
-
"out_type": None,
|
|
140
|
-
}
|
|
141
|
-
CMD_SPECIFICPOS = {
|
|
142
|
-
"name": "SPECIFICPOS",
|
|
143
|
-
"cmd": "&2 Q80={pos} Q20=13",
|
|
144
|
-
"in": 1,
|
|
145
|
-
"out": 0,
|
|
146
|
-
"return": "&2 Q20",
|
|
147
|
-
"check": Q20_3,
|
|
148
|
-
"out_type": None,
|
|
149
|
-
}
|
|
150
|
-
CMD_CLEARERROR = {
|
|
151
|
-
"name": "CLEARERROR",
|
|
152
|
-
"cmd": "&2 Q20=15",
|
|
153
|
-
"in": 0,
|
|
154
|
-
"out": 0,
|
|
155
|
-
"return": "&2 Q20",
|
|
156
|
-
"check": Q20_1,
|
|
157
|
-
"out_type": None,
|
|
158
|
-
}
|
|
159
|
-
CMD_RESETSOFT = {
|
|
160
|
-
"name": "RESETSOFT",
|
|
161
|
-
"cmd": "$$$",
|
|
162
|
-
"in": 0,
|
|
163
|
-
"out": 0,
|
|
164
|
-
"return": None,
|
|
165
|
-
"check": None,
|
|
166
|
-
"out_type": None,
|
|
167
|
-
}
|
|
168
|
-
CMD_JOG = {
|
|
169
|
-
"name": "JOG",
|
|
170
|
-
"cmd": "&2 Q68={axis} Q69={inc} Q20=41",
|
|
171
|
-
"in": 0,
|
|
172
|
-
"out": 0,
|
|
173
|
-
"return": "&2 Q20",
|
|
174
|
-
"check": Q20_2,
|
|
175
|
-
"out_type": None,
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
CMD_CFG_OFFSET = {
|
|
179
|
-
"name": "CFG#OFFSET",
|
|
180
|
-
"cmd": ("&2 Q80={grx} Q81={gry} Q20=21"),
|
|
181
|
-
"in": 2,
|
|
182
|
-
"out": 0,
|
|
183
|
-
"return": "&2 Q20",
|
|
184
|
-
"check": Q20_2,
|
|
185
|
-
"out_type": None,
|
|
186
|
-
}
|
|
187
|
-
CMD_CFG_SPEED = {
|
|
188
|
-
"name": "CFG#SPEED",
|
|
189
|
-
"cmd": "&2 Q81={sr} Q20=25",
|
|
190
|
-
"in": 1,
|
|
191
|
-
"out": 0,
|
|
192
|
-
"return": "&2 Q20",
|
|
193
|
-
"check": Q20_2,
|
|
194
|
-
"out_type": None,
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
CMD_Q20_GET = {
|
|
198
|
-
"name": "Q20?",
|
|
199
|
-
"cmd": "&2 Q20",
|
|
200
|
-
"in": 0,
|
|
201
|
-
"out": 0,
|
|
202
|
-
"return": None,
|
|
203
|
-
"check": None,
|
|
204
|
-
"out_type": None,
|
|
205
|
-
}
|
|
206
|
-
CMD_Q29_GET = {
|
|
207
|
-
"name": "Q29?",
|
|
208
|
-
"cmd": "&2 Q29",
|
|
209
|
-
"in": 0,
|
|
210
|
-
"out": 0,
|
|
211
|
-
"return": None,
|
|
212
|
-
"check": None,
|
|
213
|
-
"out_type": None,
|
|
214
|
-
}
|
|
215
|
-
CMD_STATE_HEXA_GET = {
|
|
216
|
-
"name": "STATE#HEXA?",
|
|
217
|
-
"cmd": "&2 Q36",
|
|
218
|
-
"in": 0,
|
|
219
|
-
"out": 0,
|
|
220
|
-
"return": None,
|
|
221
|
-
"check": None,
|
|
222
|
-
"out_type": None,
|
|
223
|
-
}
|
|
224
|
-
CMD_STATE_ERROR_GET = {
|
|
225
|
-
"name": "STATE#ERROR?",
|
|
226
|
-
"cmd": "&2 Q38",
|
|
227
|
-
"in": 0,
|
|
228
|
-
"out": 0,
|
|
229
|
-
"return": None,
|
|
230
|
-
"check": None,
|
|
231
|
-
"out_type": None,
|
|
232
|
-
}
|
|
233
|
-
CMD_STATE_DEBUG_GET = {
|
|
234
|
-
"name": "STATE#DEBUG?",
|
|
235
|
-
"cmd": "&2 Q26,3,1 Q20",
|
|
236
|
-
"in": 0,
|
|
237
|
-
"out": 4,
|
|
238
|
-
"return": None,
|
|
239
|
-
"check": None,
|
|
240
|
-
"out_type": int,
|
|
241
|
-
}
|
|
242
|
-
CMD_VERSION_GET = {
|
|
243
|
-
"name": "VERSION?",
|
|
244
|
-
"cmd": "&2 Q20=55",
|
|
245
|
-
"in": 0,
|
|
246
|
-
"out": 4,
|
|
247
|
-
"return": "&2 Q20 Q80,4,1",
|
|
248
|
-
"check": Q20_1,
|
|
249
|
-
"out_type": bytes.decode,
|
|
250
|
-
}
|
|
251
|
-
CMD_POSUSER_GET = {
|
|
252
|
-
"name": "POSUSER?",
|
|
253
|
-
"cmd": "&2 Q53,2,1",
|
|
254
|
-
"in": 0,
|
|
255
|
-
"out": 2,
|
|
256
|
-
"return": None,
|
|
257
|
-
"check": None,
|
|
258
|
-
"out_type": float,
|
|
259
|
-
}
|
|
260
|
-
CMD_POSVALID_GET = {
|
|
261
|
-
"name": "POSVALID?",
|
|
262
|
-
"cmd": "&2 Q70={cm} Q71={grx:.6f} Q72={gry:.6f} Q20=10",
|
|
263
|
-
"in": 3,
|
|
264
|
-
"out": 1,
|
|
265
|
-
"return": "&2 Q20 Q29",
|
|
266
|
-
"check": Q20_1,
|
|
267
|
-
"out_type": int,
|
|
268
|
-
}
|
|
269
|
-
CMD_CFG_OFFSET_GET = {
|
|
270
|
-
"name": "CFG#OFFSET?",
|
|
271
|
-
"cmd": "&2 Q20=31",
|
|
272
|
-
"in": 0,
|
|
273
|
-
"out": 2,
|
|
274
|
-
"return": "&2 Q20 Q80,2,1",
|
|
275
|
-
"check": Q20_1,
|
|
276
|
-
"out_type": float,
|
|
277
|
-
}
|
|
278
|
-
CMD_CFG_SPEED_GET = {
|
|
279
|
-
"name": "CFG#SPEED?",
|
|
280
|
-
"cmd": "&2 Q20=35",
|
|
281
|
-
"in": 0,
|
|
282
|
-
"out": 3,
|
|
283
|
-
"return": "&2 Q20 Q81,3,2",
|
|
284
|
-
"check": Q20_1,
|
|
285
|
-
"out_type": float,
|
|
286
|
-
}
|
|
287
|
-
CMD_STATE_AI_GET = {
|
|
288
|
-
"name": "STATE#AI?",
|
|
289
|
-
"cmd": "&2 Q59,2,1",
|
|
290
|
-
"in": 0,
|
|
291
|
-
"out": 2,
|
|
292
|
-
"return": None,
|
|
293
|
-
"check": None,
|
|
294
|
-
"out_type": float,
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
CMD_STRING_CID = "CID" # Card ID number
|
|
298
|
-
CMD_STRING_VER = "VERSION" # Firmware Version (Revision Level)
|
|
299
|
-
CMD_STRING_CPU = "CPU"
|
|
300
|
-
CMD_STRING_TYPE = "TYPE"
|
|
301
|
-
CMD_STRING_VID = "VID" # Vendor ID
|
|
302
|
-
CMD_STRING_DATE = "DATE"
|
|
303
|
-
CMD_STRING_TIME = "TIME"
|
|
304
|
-
CMD_STRING_TODAY = "TODAY"
|
|
305
|
-
|
|
306
|
-
DEF_TPMAC_CMD_TIMEOUT = timedelta(seconds=5)
|
|
307
|
-
DEF_TPMAC_READ_TIMEOUT = timedelta(seconds=2)
|
|
308
|
-
DEF_TPMAC_READ_FREQ = timedelta(milliseconds=100)
|
|
309
|
-
DEF_TPMAC_STRING_SIZE = 1400
|
|
310
|
-
|
|
311
|
-
DEF_STRING_SIZE = 256
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
# #### Pure Python API interface #######################################################################################
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
class PMACError(Exception):
|
|
318
|
-
pass
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
# #### Helper functions and classes ####################################################################################
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
def extractOutput(sourceStr, nr, func=bytes.decode):
|
|
325
|
-
"""
|
|
326
|
-
Extract values from the source string argument.
|
|
327
|
-
|
|
328
|
-
The output variables all have the same type and are converted using
|
|
329
|
-
the func argument, e.g. int or float.
|
|
330
|
-
|
|
331
|
-
:return: an array with the output variables.
|
|
332
|
-
"""
|
|
333
|
-
# Remove the acknowledgement from the sourceStr
|
|
334
|
-
|
|
335
|
-
sourceStr = sourceStr.rstrip(b"\r\x06")
|
|
336
|
-
|
|
337
|
-
# Split the string in it's parts separated by \r
|
|
338
|
-
|
|
339
|
-
parts = sourceStr.split(b"\r")
|
|
340
|
-
|
|
341
|
-
# extract the values from the part and put them in out
|
|
342
|
-
|
|
343
|
-
try:
|
|
344
|
-
out = [func(part) for part in parts]
|
|
345
|
-
except (ValueError, TypeError) as exc:
|
|
346
|
-
raise PMACError(
|
|
347
|
-
f'extractOutput(): Could not parse individual parts of "{sourceStr}" with {func}.'
|
|
348
|
-
) from exc
|
|
349
|
-
|
|
350
|
-
return out
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
def extractQ20AndOutput(sourceStr, nr, func=bytes.decode):
|
|
354
|
-
"""
|
|
355
|
-
Extract values from the source string argument.
|
|
356
|
-
|
|
357
|
-
The first value is always the Q20 variable and is of integer type.
|
|
358
|
-
|
|
359
|
-
The other output variables all have the same type and are converted using
|
|
360
|
-
the func argument, e.g. int or float.
|
|
361
|
-
|
|
362
|
-
Returns a tuple containing the Q20 and an array with the output variables.
|
|
363
|
-
"""
|
|
364
|
-
# Remove the acknowledgement from the sourceStr
|
|
365
|
-
|
|
366
|
-
sourceStr = sourceStr.rstrip(b"\r\x06")
|
|
367
|
-
|
|
368
|
-
# Split the string in it's parts separated by \r
|
|
369
|
-
|
|
370
|
-
parts = sourceStr.split(b"\r")
|
|
371
|
-
|
|
372
|
-
# First value is always Q20, then the other output values
|
|
373
|
-
|
|
374
|
-
try:
|
|
375
|
-
Q20 = int(parts[0])
|
|
376
|
-
out = [func(part) for part in parts[1:]]
|
|
377
|
-
except (ValueError, TypeError) as ex:
|
|
378
|
-
raise PMACError(
|
|
379
|
-
f'extractQ20AndOutput(): Could not parse individual parts of "{sourceStr}" with {func}.'
|
|
380
|
-
) from ex
|
|
381
|
-
|
|
382
|
-
return (Q20, out)
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
def decode_Q29(value):
|
|
386
|
-
"""
|
|
387
|
-
Decode the bitfield variable Q29.
|
|
388
|
-
|
|
389
|
-
Each bit in this variable represents a particular error in the validation of a movement.
|
|
390
|
-
Several errors can be combined into the Q29 variable.
|
|
391
|
-
|
|
392
|
-
Returns a dictionary with the bit numbers that were (on) and the corresponding error description.
|
|
393
|
-
"""
|
|
394
|
-
|
|
395
|
-
# This description is taken from the API Gimbal Controller Manual, version A, section 4.5.4 POSVALID?
|
|
396
|
-
|
|
397
|
-
description = [
|
|
398
|
-
"Homing is not done",
|
|
399
|
-
"Coordinate systems definition not realized",
|
|
400
|
-
"Kinematic error",
|
|
401
|
-
"Out of SYMETRIE (factory) workspace",
|
|
402
|
-
"Reserved",
|
|
403
|
-
"Out of user workspace",
|
|
404
|
-
"Actuator out of limits",
|
|
405
|
-
"Joints out of limits",
|
|
406
|
-
"Out of limits due to backlash compensation",
|
|
407
|
-
'"Abort" input enabled',
|
|
408
|
-
'"Safety Sensor" inputs enabled',
|
|
409
|
-
]
|
|
410
|
-
|
|
411
|
-
error_msgs = {}
|
|
412
|
-
|
|
413
|
-
for bit in range(24):
|
|
414
|
-
if value >> bit & 0x01:
|
|
415
|
-
error_msgs[bit] = description[bit] if bit < 11 else "Reserved"
|
|
416
|
-
|
|
417
|
-
return error_msgs
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
def decode_Q30(value):
|
|
421
|
-
"""
|
|
422
|
-
Decode the bitfield variable Q30.
|
|
423
|
-
|
|
424
|
-
Each bit in this variable represents a particular system setting of the actuator.
|
|
425
|
-
|
|
426
|
-
Returns a dictionary with the bit numbers that were (on) and the corresponding error description.
|
|
427
|
-
"""
|
|
428
|
-
|
|
429
|
-
# This description is taken from the API Gimbal Controller Manual, version A, section 4.5.5 STATE#ACTUATOR?
|
|
430
|
-
|
|
431
|
-
description = [
|
|
432
|
-
"In position",
|
|
433
|
-
"Control loop on servo motors active",
|
|
434
|
-
"Homing done",
|
|
435
|
-
'Input "Home switch"',
|
|
436
|
-
'Input "Positive limit switch"',
|
|
437
|
-
'Input "Negative limit switch"',
|
|
438
|
-
"Brake control output",
|
|
439
|
-
"Following error (warning)",
|
|
440
|
-
"Following error",
|
|
441
|
-
"Actuator out of bounds error",
|
|
442
|
-
"Amplifier error",
|
|
443
|
-
"Encoder error",
|
|
444
|
-
"Phasing error (brushless engine only)",
|
|
445
|
-
]
|
|
446
|
-
|
|
447
|
-
error_msgs = {
|
|
448
|
-
bit: description[bit] if bit < 13 else "Reserved"
|
|
449
|
-
for bit in range(24)
|
|
450
|
-
if value >> bit & 0x01
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
states = [int(x) for x in f"{value:024b}"[::-1]]
|
|
454
|
-
|
|
455
|
-
return error_msgs, states
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
def decode_Q36(value):
|
|
459
|
-
"""
|
|
460
|
-
Decode the bitfield variable Q36.
|
|
461
|
-
|
|
462
|
-
Each bit in this variable represents the status of a particular system setting of the gimbal.
|
|
463
|
-
|
|
464
|
-
Returns an array with the value (True/False) of the individual bits.
|
|
465
|
-
"""
|
|
466
|
-
|
|
467
|
-
# This description is taken from the API Gimbal Controller Manual, version A, section 4.5.6 STATE#HEXA?
|
|
468
|
-
|
|
469
|
-
description = [ # noqa: F841
|
|
470
|
-
"Error (OR)",
|
|
471
|
-
"System Initialized",
|
|
472
|
-
"In position",
|
|
473
|
-
"Control loop on servo motors active",
|
|
474
|
-
"Homing done",
|
|
475
|
-
"Brake control output",
|
|
476
|
-
"Emergency stop button engaged",
|
|
477
|
-
"Following error (warning)",
|
|
478
|
-
"Following error",
|
|
479
|
-
"Actuator out of bounds error or safety sensor error",
|
|
480
|
-
"Amplifier Error",
|
|
481
|
-
"Encoder error",
|
|
482
|
-
"Phasing error (brushless motors only)",
|
|
483
|
-
"Homing error",
|
|
484
|
-
"Kinematic error",
|
|
485
|
-
'"Abort" input error',
|
|
486
|
-
"R/W flash memory error",
|
|
487
|
-
"Temperature error on one or several motors",
|
|
488
|
-
"Home done (virtual)",
|
|
489
|
-
"Encoders power off",
|
|
490
|
-
"Limit switches power off",
|
|
491
|
-
"Reserved",
|
|
492
|
-
"Reserved",
|
|
493
|
-
"Reserved",
|
|
494
|
-
]
|
|
495
|
-
|
|
496
|
-
bit_values = [False for x in range(24)]
|
|
497
|
-
|
|
498
|
-
for bit in range(24):
|
|
499
|
-
bit_values[bit] = True if value >> bit & 0x01 else False
|
|
500
|
-
|
|
501
|
-
return bit_values
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
class EthernetCommand:
|
|
505
|
-
def __init__(self, requestType, request, value, index):
|
|
506
|
-
self.requestType = requestType # type is byte
|
|
507
|
-
self.request = request # type is byte
|
|
508
|
-
self.value = value # type is word (= 2 bytes), content request specific
|
|
509
|
-
self.index = index # type is word
|
|
510
|
-
self.length = None # type is word, length of the data part
|
|
511
|
-
self.data = [] # type is byte, max length = 1492 bytes
|
|
512
|
-
|
|
513
|
-
def getCommandPacket(self, command=None):
|
|
514
|
-
"""
|
|
515
|
-
Pack and return the header and the command in a bytes packet.
|
|
516
|
-
"""
|
|
517
|
-
if command is None:
|
|
518
|
-
command = ""
|
|
519
|
-
|
|
520
|
-
assert type(command) == str
|
|
521
|
-
|
|
522
|
-
headerStr = struct.pack(
|
|
523
|
-
">BBHHH", self.requestType, self.request, self.value, self.index, len(command)
|
|
524
|
-
)
|
|
525
|
-
wrappedCommand = headerStr + command.encode()
|
|
526
|
-
|
|
527
|
-
logger.flash_flood(f"Command Packet generated: {wrappedCommand}")
|
|
528
|
-
|
|
529
|
-
return wrappedCommand
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
class PmacEthernetInterface(object):
|
|
533
|
-
"""
|
|
534
|
-
This class provides an interface to connect to a remote PMAC over an Ethernet interface.
|
|
535
|
-
It provides methods to connect to the PMAC, to disconnect, and to issue commands.
|
|
536
|
-
"""
|
|
537
|
-
|
|
538
|
-
def __init__(self, numAxes=None):
|
|
539
|
-
"""
|
|
540
|
-
Initialize the PMAC Ethernet interface.
|
|
541
|
-
"""
|
|
542
|
-
self.modelName = None # Will be initialized by the getPmacModel() call
|
|
543
|
-
|
|
544
|
-
# Basic connection settings
|
|
545
|
-
|
|
546
|
-
self.hostname = ""
|
|
547
|
-
self.port = None
|
|
548
|
-
|
|
549
|
-
# Access-to-the-connection semaphore.
|
|
550
|
-
# Use this to lock/unlock I/O access to the connection (whatever type it is) in child classes.
|
|
551
|
-
|
|
552
|
-
self.semaphore = threading.Semaphore()
|
|
553
|
-
|
|
554
|
-
self.isConnectionOpen = False
|
|
555
|
-
|
|
556
|
-
# Use the getter self.getNumberOfAxes() to access this. The value is None if uninitialised.
|
|
557
|
-
|
|
558
|
-
if numAxes is not None:
|
|
559
|
-
self._numAxes = int(numAxes)
|
|
560
|
-
else:
|
|
561
|
-
self._numAxes = None
|
|
562
|
-
|
|
563
|
-
# Define a number of often used commands
|
|
564
|
-
|
|
565
|
-
self.getResponseCommand = EthernetCommand(VR_DOWNLOAD, VR_PMAC_GETRESPONSE, 0, 0)
|
|
566
|
-
self.getBufferCommand = EthernetCommand(VR_UPLOAD, VR_PMAC_GETBUFFER, 0, 0)
|
|
567
|
-
|
|
568
|
-
def setConnectionParameters(self, host="localhost", port=None):
|
|
569
|
-
self.hostname = str(host)
|
|
570
|
-
if port is not None:
|
|
571
|
-
self.port = int(str(port))
|
|
572
|
-
|
|
573
|
-
# Attempts to open a connection to a remote PMAC.
|
|
574
|
-
# Returns None on success, or an error message string on failure.
|
|
575
|
-
|
|
576
|
-
def connect(self):
|
|
577
|
-
|
|
578
|
-
# Sanity checks
|
|
579
|
-
if self.isConnectionOpen:
|
|
580
|
-
raise PMACError("Socket is already open")
|
|
581
|
-
if self.hostname in (None, ""):
|
|
582
|
-
raise PMACError("ERROR: hostname not initialized")
|
|
583
|
-
if self.port in (None, 0):
|
|
584
|
-
raise PMACError("ERROR: port number not initialized")
|
|
585
|
-
|
|
586
|
-
# Create a new socket instance
|
|
587
|
-
|
|
588
|
-
try:
|
|
589
|
-
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
590
|
-
self.sock.setblocking(1)
|
|
591
|
-
self.sock.settimeout(3)
|
|
592
|
-
except socket.error as e_socket:
|
|
593
|
-
raise PMACError("ERROR: Failed to create socket.") from e_socket
|
|
594
|
-
|
|
595
|
-
# Attempt to establish a connection to the remote host
|
|
596
|
-
|
|
597
|
-
try:
|
|
598
|
-
logger.debug(f'Connecting a socket to host "{self.hostname}" using port {self.port}')
|
|
599
|
-
self.sock.connect((self.hostname, self.port))
|
|
600
|
-
except ConnectionRefusedError as e_cr:
|
|
601
|
-
raise PMACError(f"ERROR: Connection refused to {self.hostname}") from e_cr
|
|
602
|
-
except socket.gaierror as e_gai:
|
|
603
|
-
raise PMACError(f"ERROR: socket address info error for {self.hostname}") from e_gai
|
|
604
|
-
except socket.herror as e_h:
|
|
605
|
-
raise PMACError(f"ERROR: socket host address error for {self.hostname}") from e_h
|
|
606
|
-
except socket.timeout as e_timeout:
|
|
607
|
-
raise PMACError(f"ERROR: socket timeout error for {self.hostname}") from e_timeout
|
|
608
|
-
except OSError as ose:
|
|
609
|
-
raise PMACError(f"ERROR: OSError caught ({ose}).") from ose
|
|
610
|
-
|
|
611
|
-
self.isConnectionOpen = True
|
|
612
|
-
|
|
613
|
-
# Check that we are connected to a pmac by issuing the "VERSION" command -- expecting the 1.947 in return.
|
|
614
|
-
# If we don't get the right response, then disconnect automatically
|
|
615
|
-
|
|
616
|
-
if not self.isConnected():
|
|
617
|
-
raise PMACError("Device is not connected, check logging messages for the cause.")
|
|
618
|
-
|
|
619
|
-
def disconnect(self):
|
|
620
|
-
"""
|
|
621
|
-
Disconnect from the Ethernet connection.
|
|
622
|
-
|
|
623
|
-
Raises a PMACError on failure.
|
|
624
|
-
"""
|
|
625
|
-
try:
|
|
626
|
-
if self.isConnectionOpen:
|
|
627
|
-
logger.debug(f"Disconnecting from {self.hostname}")
|
|
628
|
-
self.semaphore.acquire()
|
|
629
|
-
self.sock.close()
|
|
630
|
-
self.semaphore.release()
|
|
631
|
-
self.isConnectionOpen = False
|
|
632
|
-
except Exception as e_exc:
|
|
633
|
-
raise PMACError(f"Could not close socket to {self.hostname}") from e_exc
|
|
634
|
-
|
|
635
|
-
def isConnected(self):
|
|
636
|
-
"""
|
|
637
|
-
Check if the PMAC Ethernet connection is open. This will send a 'version' command to the
|
|
638
|
-
PMAC interface and try to parse the return value. If no connection was established or
|
|
639
|
-
no version could be parsed from the return value, False is returned.
|
|
640
|
-
"""
|
|
641
|
-
if not self.isConnectionOpen:
|
|
642
|
-
return False
|
|
643
|
-
|
|
644
|
-
try:
|
|
645
|
-
response = self.getResponse(CMD_STRING_VER)
|
|
646
|
-
except PMACError as e_pmac:
|
|
647
|
-
if len(e_pmac.args) >= 2 and e_pmac.args[1] == ERR_CONNECTION:
|
|
648
|
-
logger.error(
|
|
649
|
-
f"While trying to talk to the device the following exception occurred, exception={e_pmac}"
|
|
650
|
-
)
|
|
651
|
-
logger.error("Most probably the client connection was closed. Disconnecting...")
|
|
652
|
-
self.disconnect()
|
|
653
|
-
return False
|
|
654
|
-
else:
|
|
655
|
-
logger.error(
|
|
656
|
-
f"While trying to talk to the device the following exception occured, exception={e_pmac}"
|
|
657
|
-
)
|
|
658
|
-
self.disconnect()
|
|
659
|
-
return False
|
|
660
|
-
finally:
|
|
661
|
-
pass
|
|
662
|
-
|
|
663
|
-
version = match_float_response(response)
|
|
664
|
-
|
|
665
|
-
if not version:
|
|
666
|
-
# if the response was not matching the regex then we're not talking to a PMAC!
|
|
667
|
-
logger.error(
|
|
668
|
-
f'Device did not respond correctly to a "VERSION" command, response={response}. Disconnecting...'
|
|
669
|
-
)
|
|
670
|
-
self.disconnect()
|
|
671
|
-
return False
|
|
672
|
-
|
|
673
|
-
return True
|
|
674
|
-
|
|
675
|
-
def getBuffer(self, shouldWait=True):
|
|
676
|
-
""""""
|
|
677
|
-
|
|
678
|
-
if not self.isConnectionOpen:
|
|
679
|
-
raise PMACError("Device is not connected, reconnect or check logging messages.")
|
|
680
|
-
|
|
681
|
-
try:
|
|
682
|
-
if shouldWait:
|
|
683
|
-
self.semaphore.acquire()
|
|
684
|
-
|
|
685
|
-
# Attempt to send the complete command to PMAC
|
|
686
|
-
|
|
687
|
-
self.sock.sendall(self.getBufferCommand.getCommandPacket())
|
|
688
|
-
logger.debug("Sent out get buffer request to PMAC")
|
|
689
|
-
|
|
690
|
-
# wait for, read and return the response from PMAC (will be at most 1400 chars)
|
|
691
|
-
|
|
692
|
-
returnStr = self.sock.recv(2048)
|
|
693
|
-
logger.debug(f"Received from PMAC: {returnStr}")
|
|
694
|
-
|
|
695
|
-
return returnStr
|
|
696
|
-
|
|
697
|
-
except socket.timeout as e_timeout:
|
|
698
|
-
raise PMACError("Socket timeout error", ERR_CMD_TIMEOUT) from e_timeout
|
|
699
|
-
except socket.error as e_socket:
|
|
700
|
-
# Interpret any socket-related error as an I/O error
|
|
701
|
-
raise PMACError("Socket communication error.", ERR_CONNECTION) from e_socket
|
|
702
|
-
except OSError as e_os:
|
|
703
|
-
raise PMACError(f"OS Error: {e_os}") from e_os
|
|
704
|
-
finally:
|
|
705
|
-
if shouldWait:
|
|
706
|
-
self.semaphore.release()
|
|
707
|
-
|
|
708
|
-
def getResponse(self, command, shouldWait=True):
|
|
709
|
-
"""
|
|
710
|
-
Send a single command to the controller and block until a response from the controller.
|
|
711
|
-
|
|
712
|
-
Args:
|
|
713
|
-
command (str): is the command to be sent
|
|
714
|
-
|
|
715
|
-
shouldWait (bool, optional, default True): whether to wait on the semaphore.
|
|
716
|
-
|
|
717
|
-
This should normally be left default. If we have acquired the semaphore manually,
|
|
718
|
-
then specify shouldWait = False (and don't forget to release the semaphore eventually).
|
|
719
|
-
|
|
720
|
-
Returns:
|
|
721
|
-
response (str): is either a string returned by the PMAC (on success), or an error message (on failure)
|
|
722
|
-
|
|
723
|
-
Raises:
|
|
724
|
-
PMACError when there was an I/O problem during comm with the PMAC or the response does not have
|
|
725
|
-
recognised terminators.
|
|
726
|
-
|
|
727
|
-
Note that PMAC may still return an "ERRxxx" code; this function will still consider that
|
|
728
|
-
a successful transmission.
|
|
729
|
-
|
|
730
|
-
"""
|
|
731
|
-
|
|
732
|
-
if not self.isConnectionOpen:
|
|
733
|
-
raise PMACError("Device is not connected, reconnect or check logging messages.")
|
|
734
|
-
|
|
735
|
-
command = str(command)
|
|
736
|
-
|
|
737
|
-
try:
|
|
738
|
-
if shouldWait:
|
|
739
|
-
self.semaphore.acquire()
|
|
740
|
-
|
|
741
|
-
# Attempt to send the complete command to PMAC
|
|
742
|
-
|
|
743
|
-
logger.flash_flood(f"Sending out to PMAC: {command}")
|
|
744
|
-
self.sock.sendall(self.getResponseCommand.getCommandPacket(command))
|
|
745
|
-
|
|
746
|
-
# wait for, read and return the response from PMAC (will be at most 1400 chars)
|
|
747
|
-
|
|
748
|
-
returnStr = self.sock.recv(2048)
|
|
749
|
-
logger.flash_flood( f"Received from PMAC: {returnStr}")
|
|
750
|
-
|
|
751
|
-
return returnStr
|
|
752
|
-
|
|
753
|
-
except OSError as e_os:
|
|
754
|
-
raise PMACError(f"OS Error: {e_os}") from e_os
|
|
755
|
-
except socket.timeout as e_timeout:
|
|
756
|
-
raise PMACError("Socket timeout error", ERR_CMD_TIMEOUT) from e_timeout
|
|
757
|
-
except socket.error as e_socket:
|
|
758
|
-
# Interpret any socket-related error as an I/O error
|
|
759
|
-
raise PMACError("Socket communication error.", ERR_CONNECTION) from e_socket
|
|
760
|
-
finally:
|
|
761
|
-
if shouldWait:
|
|
762
|
-
self.semaphore.release()
|
|
763
|
-
|
|
764
|
-
def waitFor(self, cmd, values):
|
|
765
|
-
start = datetime.now()
|
|
766
|
-
count = 0
|
|
767
|
-
|
|
768
|
-
assert isinstance(values, list), "Expected list argument"
|
|
769
|
-
|
|
770
|
-
while datetime.now() - start < DEF_TPMAC_CMD_TIMEOUT:
|
|
771
|
-
|
|
772
|
-
# Only read every DEF_TPMAC_READ_FREQ
|
|
773
|
-
|
|
774
|
-
if datetime.now() - start > count * DEF_TPMAC_READ_FREQ:
|
|
775
|
-
count += 1
|
|
776
|
-
retStr = self.getResponse(cmd)
|
|
777
|
-
key = match_int_response(retStr)
|
|
778
|
-
if key in values:
|
|
779
|
-
return key
|
|
780
|
-
|
|
781
|
-
raise PMACError(f"Timeout while waiting for {cmd} to be {values}")
|
|
782
|
-
|
|
783
|
-
def waitForOutput(self, cmd, values, nr, func):
|
|
784
|
-
start = datetime.now()
|
|
785
|
-
count = 0
|
|
786
|
-
|
|
787
|
-
assert isinstance(values, list), "Expected list argument"
|
|
788
|
-
|
|
789
|
-
while datetime.now() - start < DEF_TPMAC_CMD_TIMEOUT:
|
|
790
|
-
|
|
791
|
-
# Only read every DEF_TPMAC_READ_FREQ
|
|
792
|
-
|
|
793
|
-
if datetime.now() - start > count * DEF_TPMAC_READ_FREQ:
|
|
794
|
-
count += 1
|
|
795
|
-
retStr = self.getResponse(cmd)
|
|
796
|
-
Q20, out = extractQ20AndOutput(retStr, nr, func)
|
|
797
|
-
if Q20 not in values:
|
|
798
|
-
continue
|
|
799
|
-
return out
|
|
800
|
-
|
|
801
|
-
raise PMACError(f"Timeout while waiting for {cmd} to be {values}")
|
|
802
|
-
|
|
803
|
-
def getQVars(self, base, offsets, func=bytes.decode):
|
|
804
|
-
"""
|
|
805
|
-
Get a list of values of Qxx variables, where xx = base + offset (for each offset).
|
|
806
|
-
|
|
807
|
-
Throws a PMACError when no response received from Gimbal Hardware Controller.
|
|
808
|
-
"""
|
|
809
|
-
qVars = map(lambda x: base + x, offsets)
|
|
810
|
-
cmd = ""
|
|
811
|
-
for qVar in qVars:
|
|
812
|
-
cmd += f"Q{qVar:02} "
|
|
813
|
-
retStr = self.getResponse(cmd)
|
|
814
|
-
logger.flash_flood(f"retStr={retStr} of type {type(retStr)}")
|
|
815
|
-
|
|
816
|
-
if retStr == b"\x00":
|
|
817
|
-
raise PMACError(f"No response received for {cmd}, return value is {retStr}")
|
|
818
|
-
|
|
819
|
-
# Remove the acknowledgement from the sourceStr
|
|
820
|
-
|
|
821
|
-
retStr = retStr.rstrip(b"\r\x06")
|
|
822
|
-
|
|
823
|
-
# Split the string in it's parts separated by \r
|
|
824
|
-
|
|
825
|
-
qVarsResult = [func(x) for x in retStr.split(b"\r")]
|
|
826
|
-
|
|
827
|
-
return qVarsResult
|
|
828
|
-
|
|
829
|
-
def getMVars(self, base, offsets, func=bytes.decode):
|
|
830
|
-
"""
|
|
831
|
-
Get a list of values of Mxx variables, where xx = base + offset (for each offset).
|
|
832
|
-
|
|
833
|
-
The 'M' variables are Symétrie internal variables.
|
|
834
|
-
The following M-Vars are known:
|
|
835
|
-
|
|
836
|
-
* M5282 - check if a motion program is running, return 1 when it is running, 0 if no motion program is running
|
|
837
|
-
|
|
838
|
-
Throws a PMACError when no response received from Gimbal Hardware Controller.
|
|
839
|
-
"""
|
|
840
|
-
mVars = map(lambda x: base + x, offsets)
|
|
841
|
-
cmd = ""
|
|
842
|
-
for mVar in mVars:
|
|
843
|
-
cmd += f"M{mVar:02} "
|
|
844
|
-
retStr = self.getResponse(cmd)
|
|
845
|
-
logger.debug(f"retStr={retStr} of type {type(retStr)}")
|
|
846
|
-
|
|
847
|
-
if retStr == b"\x00":
|
|
848
|
-
raise PMACError(f"No response received for {cmd}, return value is {retStr}")
|
|
849
|
-
|
|
850
|
-
# Remove the acknowledgement from the sourceStr
|
|
851
|
-
|
|
852
|
-
retStr = retStr.rstrip(b"\r\x06")
|
|
853
|
-
|
|
854
|
-
# Split the string in it's parts separated by \r
|
|
855
|
-
|
|
856
|
-
mVarsResult = [func(x) for x in retStr.split(b"\r")]
|
|
857
|
-
|
|
858
|
-
return mVarsResult
|
|
859
|
-
|
|
860
|
-
def getIVars(self, base, offsets, func=bytes.decode):
|
|
861
|
-
"""
|
|
862
|
-
Get a list of values of Ixxxx variables, where xxxx = base + offset (for each offset).
|
|
863
|
-
"""
|
|
864
|
-
iVars = map(lambda x: base + x, offsets)
|
|
865
|
-
cmd = ""
|
|
866
|
-
for iVar in iVars:
|
|
867
|
-
cmd += "i%d " % iVar
|
|
868
|
-
retStr = self.getResponse(cmd)
|
|
869
|
-
logger.debug(f"retStr={retStr} of type {type(retStr)}")
|
|
870
|
-
|
|
871
|
-
# Remove the acknowledgement from the sourceStr
|
|
872
|
-
|
|
873
|
-
retStr = retStr.rstrip(b"\r\x06")
|
|
874
|
-
|
|
875
|
-
# Split the string in it's parts separated by \r
|
|
876
|
-
|
|
877
|
-
iVarsResult = [func(x) for x in retStr.split(b"\r")]
|
|
878
|
-
|
|
879
|
-
return iVarsResult
|
|
880
|
-
|
|
881
|
-
def getPmacModel(self):
|
|
882
|
-
"""
|
|
883
|
-
Return a string designating which PMAC model this is.
|
|
884
|
-
|
|
885
|
-
Raise a PMACError if the model is unknown.
|
|
886
|
-
"""
|
|
887
|
-
|
|
888
|
-
if self.modelName:
|
|
889
|
-
return self.modelName
|
|
890
|
-
|
|
891
|
-
# Ask for pmac model, returns an integer
|
|
892
|
-
|
|
893
|
-
modelCode = self.getCID()
|
|
894
|
-
|
|
895
|
-
# Return a model designation based on model code
|
|
896
|
-
|
|
897
|
-
modelNamesByCode = {602413: "Turbo PMAC2-VME", 603382: "Geo Brick (3U Turbo PMAC2)"}
|
|
898
|
-
try:
|
|
899
|
-
modelName = modelNamesByCode[modelCode]
|
|
900
|
-
except KeyError as e_key:
|
|
901
|
-
raise PMACError(f"Unsupported PMAC model: modelCode={modelCode}") from e_key
|
|
902
|
-
|
|
903
|
-
self.modelName = modelName
|
|
904
|
-
|
|
905
|
-
return modelName
|
|
906
|
-
|
|
907
|
-
def getCID(self):
|
|
908
|
-
retStr = self.getResponse(CMD_STRING_CID)
|
|
909
|
-
return match_int_response(retStr)
|
|
910
|
-
|
|
911
|
-
def getVersion(self):
|
|
912
|
-
retStr = self.getResponse(CMD_STRING_VER)
|
|
913
|
-
return match_float_response(retStr)
|
|
914
|
-
|
|
915
|
-
def getCPU(self):
|
|
916
|
-
retStr = self.getResponse(CMD_STRING_CPU)
|
|
917
|
-
return match_string_response(retStr)
|
|
918
|
-
|
|
919
|
-
def getType(self):
|
|
920
|
-
retStr = self.getResponse(CMD_STRING_TYPE)
|
|
921
|
-
return match_string_response(retStr)
|
|
922
|
-
|
|
923
|
-
def getVID(self):
|
|
924
|
-
retStr = self.getResponse(CMD_STRING_VID)
|
|
925
|
-
return match_string_response(retStr)
|
|
926
|
-
|
|
927
|
-
def getDate(self):
|
|
928
|
-
retStr = self.getResponse(CMD_STRING_DATE)
|
|
929
|
-
return match_string_response(retStr)
|
|
930
|
-
|
|
931
|
-
def getTime(self):
|
|
932
|
-
retStr = self.getResponse(CMD_STRING_TIME)
|
|
933
|
-
return match_string_response(retStr)
|
|
934
|
-
|
|
935
|
-
def getToday(self):
|
|
936
|
-
retStr = self.getResponse(CMD_STRING_TODAY)
|
|
937
|
-
return match_string_response(retStr)
|
|
938
|
-
|
|
939
|
-
def sendCommand(self, cmd, **kwargs):
|
|
940
|
-
"""
|
|
941
|
-
Sends a command string to the TPMAC.
|
|
942
|
-
|
|
943
|
-
Once the acknowledgment is received, it interrogates the TPMAC Q20 variable
|
|
944
|
-
each DEF_TPMAC_READ_FREQ microseconds until Q20 = 0 or -1 or -2.
|
|
945
|
-
|
|
946
|
-
Throws a PMACError:
|
|
947
|
-
* when the arguments do not match up
|
|
948
|
-
* when there is a Time-Out
|
|
949
|
-
* when there is a socket communication error
|
|
950
|
-
|
|
951
|
-
Returns the Q20 value as an integer.
|
|
952
|
-
"""
|
|
953
|
-
|
|
954
|
-
# When we expect input parameters, make sure the number of **kwargs matches the cmd['in']
|
|
955
|
-
# and format the command with the given keyword arguments.raise
|
|
956
|
-
|
|
957
|
-
if cmd["in"] > 0:
|
|
958
|
-
if len(kwargs) == cmd["in"]:
|
|
959
|
-
fullCommand = cmd["cmd"].format(**kwargs)
|
|
960
|
-
else:
|
|
961
|
-
raise PMACError(
|
|
962
|
-
f"Expected {cmd['in']} keyword arguments to cmd['name'], got {len(kwargs)}"
|
|
963
|
-
)
|
|
964
|
-
else:
|
|
965
|
-
fullCommand = cmd["cmd"]
|
|
966
|
-
|
|
967
|
-
logger.flash_flood(f'Sending the {cmd["name"]} command.')
|
|
968
|
-
|
|
969
|
-
retStr = self.getResponse(fullCommand)
|
|
970
|
-
|
|
971
|
-
logger.flash_flood(f'Command \'{cmd["name"]}\' returned "{retStr}"')
|
|
972
|
-
|
|
973
|
-
# Check the return code (usually Q20)
|
|
974
|
-
|
|
975
|
-
if cmd["out"] == 0 and cmd["return"] is not None:
|
|
976
|
-
|
|
977
|
-
# The following method can throw a PMACError on Timeout
|
|
978
|
-
|
|
979
|
-
rc = self.waitFor(cmd["return"], cmd["check"])
|
|
980
|
-
logger.debug(f"waitFor returned {rc}")
|
|
981
|
-
|
|
982
|
-
return rc
|
|
983
|
-
|
|
984
|
-
# Get and return the output parameters
|
|
985
|
-
|
|
986
|
-
if cmd["out"] > 0 and cmd["return"] is not None:
|
|
987
|
-
|
|
988
|
-
# The following method can throw a PMACError on Timeout
|
|
989
|
-
|
|
990
|
-
out = self.waitForOutput(cmd["return"], cmd["check"], cmd["out"], cmd["out_type"])
|
|
991
|
-
logger.debug(f"waitForAndOutput returned {out}")
|
|
992
|
-
|
|
993
|
-
return out
|
|
994
|
-
|
|
995
|
-
# Get the output parameters out of the retStr
|
|
996
|
-
|
|
997
|
-
if cmd["out"] > 0 and cmd["return"] is None:
|
|
998
|
-
out = extractOutput(retStr, cmd["out"], cmd["out_type"])
|
|
999
|
-
|
|
1000
|
-
return out
|
|
1001
|
-
#
|
|
1002
|
-
return None
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
if __name__ == "__main__":
|
|
1006
|
-
pass
|