From 43bc539b135a2a90baa99332ed96478187508fef Mon Sep 17 00:00:00 2001 From: gac-S_Changer Date: Thu, 14 Feb 2019 10:47:43 +0100 Subject: [PATCH] Creation --- config/config.properties | 32 + config/devices - Copy.properties | 67 + config/devices-modbus.properties | 50 + config/devices.properties | 80 + config/jcae.properties | 11 + config/mail.properties | 9 + config/plugins.properties | 21 + config/settings.properties | 17 + config/setup-modbus.properties | 18 + config/setup.properties | 19 + config/tasks.properties | 1 + devices/20161117_163816.png.properties | 20 + devices/A1.properties | 3 + devices/A2.properties | 3 + devices/A3.properties | 3 + devices/A4.properties | 3 + devices/A5.properties | 3 + devices/B1.properties | 3 + devices/B2.properties | 3 + devices/B3.properties | 3 + devices/B4.properties | 3 + devices/B5.properties | 3 + devices/BasePlate.properties | 1 + devices/C1.properties | 3 + devices/C2.properties | 3 + devices/C3.properties | 3 + devices/C4.properties | 3 + devices/C5.properties | 3 + devices/D1.properties | 3 + devices/D2.properties | 3 + devices/D3.properties | 3 + devices/D4.properties | 3 + devices/D5.properties | 3 + devices/E1.properties | 3 + devices/E2.properties | 3 + devices/E3.properties | 3 + devices/E4.properties | 3 + devices/E5.properties | 3 + devices/F1.properties | 3 + devices/F2.properties | 3 + devices/F3.properties | 3 + devices/F4.properties | 3 + devices/F5.properties | 3 + devices/Time.properties | 10 + devices/air_pressure.properties | 5 + devices/cx.properties | 17 + devices/cz.properties | 17 + devices/dewar_level.properties | 6 + devices/dispatcher.properties | 11 + devices/dp1.properties | 11 + devices/fx.properties | 17 + devices/fy.properties | 17 + devices/gripper_cam.properties | 20 + devices/img.properties | 24 + devices/led_ctrl.properties | 8 + devices/led_ctrl_1.properties | 9 + devices/led_ctrl_2.properties | 9 + devices/led_ctrl_3.properties | 9 + devices/led_level.properties | 9 + devices/m1.properties | 13 + devices/m2.properties | 13 + devices/monitoring_cam.properties | 20 + devices/n2_pressure.properties | 5 + devices/p1.properties | 9 + devices/phase_separator.properties | 8 + devices/phase_separator_level.properties | 6 + devices/rim_heater_temp.properties | 6 + devices/robot x.properties | 9 + devices/robot.properties | 8 + devices/robot_j1.properties | 10 + devices/robot_j2.properties | 10 + devices/robot_j3.properties | 10 + devices/robot_j4.properties | 10 + devices/robot_j5.properties | 10 + devices/robot_j6.properties | 10 + devices/robot_modbus.properties | 8 + devices/robot_rx.properties | 10 + devices/robot_ry.properties | 10 + devices/robot_rz.properties | 10 + devices/robot_x.properties | 10 + devices/robot_y.properties | 10 + devices/robot_z.properties | 10 + devices/ry.properties | 17 + devices/smart_magnet.properties | 8 + devices/smc_current.properties | 9 + devices/smc_current_rb.properties | 6 + devices/src1.properties | 24 + devices/src2.properties | 24 + devices/top_cam.properties | 20 + devices/ue.properties | 6 + devices/wago.properties | 8 + plugins/BarcodeReaderPanel.form | 118 ++ plugins/BarcodeReaderPanel.java | 162 ++ plugins/Beeper.java | 72 + plugins/Commands.form | 803 ++++++++ plugins/Commands.java | 914 +++++++++ plugins/Hexiposi.form | 34 + plugins/Hexiposi.java | 78 + plugins/HexiposiPanel.form | 81 + plugins/HexiposiPanel.java | 110 ++ plugins/LN2.form | 34 + plugins/LN2.java | 106 ++ plugins/LaserUE.java | 79 + plugins/LaserUEPanel.form | 59 + plugins/LaserUEPanel.java | 98 + plugins/MXSC-1.10.0.jar | Bin 0 -> 272262 bytes plugins/MXSC-1.10.0.jar.back | Bin 0 -> 263817 bytes plugins/MjpegSource2.java | 149 ++ plugins/NewJPanel.form | 136 ++ plugins/NewJPanel.java | 217 +++ plugins/PuckDetectionPanel.form | 184 ++ plugins/PuckDetectionPanel.java | 251 +++ plugins/Recovery.form | 140 ++ plugins/Recovery.java | 255 +++ plugins/RobotModbus.java | 21 + plugins/RobotPanel.form | 587 ++++++ plugins/RobotPanel.java | 685 +++++++ plugins/RobotTcp.java | 21 + plugins/SmartMagnetConfig.java | 14 + plugins/SmartMagnetPanel.form | 221 +++ plugins/SmartMagnetPanel.java | 234 +++ plugins/TestZMQ.java | 26 + plugins/WagoPanel.form | 167 ++ plugins/WagoPanel.java | 207 +++ plugins/gui.form | 62 + plugins/gui.java | 96 + script/LN2_Monitoring.scd | 15 + script/LevelMonitoring.scd | 12 + script/calibration/BinarySearchYZ.py | 29 + script/calibration/HillClimbingXZ.py | 45 + script/calibration/ScanRZ.py | 31 + script/calibration/ScanX.py | 81 + script/calibration/ScanY.py | 81 + script/calibration/ScanYZ.py | 93 + script/calibration/ToolCalibration.py | 60 + script/calibration/ToolCalibration2.py | 86 + script/calibration/ToolCalibration3.py | 83 + script/client/PShellClient.py | 369 ++++ script/client/TellClient.py | 184 ++ script/client/sseclient.py | 163 ++ script/client/tell.py | 79 + script/data/get_samples_info.py | 4 + script/data/pucks.py | 22 + script/data/samples.py | 332 ++++ script/data/set_samples_info.py | 4 + script/devices/BarcodeReader.py | 82 + script/devices/Gonio.py | 43 + script/devices/Hexiposi.py | 173 ++ script/devices/LaserDistance.py | 17 + script/devices/LedCtrl.py | 46 + script/devices/OneWire.py | 134 ++ script/devices/RobotModbus.py | 46 + script/devices/RobotMotors.py | 62 + script/devices/RobotSC.py | 315 ++++ script/devices/RobotTCP.py | 865 +++++++++ script/devices/SmartMagnet.py | 129 ++ script/devices/Wago.py | 141 ++ script/hexiposi_positon.scd | 11 + script/imgproc/CameraCalibration.py | 155 ++ script/imgproc/CoverDetection.py | 98 + script/imgproc/CoverDetectionCalibration.py | 40 + script/imgproc/CreateMask.py | 29 + script/imgproc/LedDetectionFilter.py | 102 + script/imgproc/LedDetectionProc.py | 106 ++ script/imgproc/Utils.py | 113 ++ script/local.groovy | 3 + script/local.js | 4 + script/local.py | 413 ++++ script/motion/calibrate_tool.py | 32 + script/motion/dry.py | 48 + script/motion/get_aux.py | 21 + script/motion/get_dewar.py | 30 + script/motion/get_gonio.py | 20 + script/motion/homing_hexiposi.py | 18 + script/motion/mount.py | 134 ++ script/motion/move_aux.py | 18 + script/motion/move_cold.py | 22 + script/motion/move_dewar.py | 18 + script/motion/move_gonio.py | 18 + script/motion/move_heater.py | 18 + script/motion/move_home.py | 18 + script/motion/move_park.py | 18 + script/motion/move_scanner.py | 30 + script/motion/put_aux.py | 21 + script/motion/put_dewar.py | 30 + script/motion/put_gonio.py | 23 + script/motion/recover.py | 163 ++ script/motion/robot_recover.py | 16 + script/motion/scan_pin.py | 94 + script/motion/tools.py | 179 ++ script/motion/trash.py | 36 + script/motion/unmount.py | 87 + script/setup/ExposureScan.py | 33 + script/setup/Layout.py | 292 +++ script/tasks/LedMonitoring.py | 26 + script/test/CameraCalibration.py | 71 + script/test/CoverDetection.py | 116 ++ script/test/PuckDetection.py | 24 + script/test/PuckDetectionTest.py | 11 + script/test/RobotCartesianScan.py | 28 + script/test/SampleDataInput.py | 1861 ++++++++++++++++++ script/test/SampleDataInput_Dominik.py | 1862 +++++++++++++++++++ script/test/SampleDetection.py | 23 + script/test/TestAlign.py | 9 + script/test/TestBugPcAPI | 4 + script/test/TestBugPcAPI.py | 30 + script/test/TestBugPcAPI2.py | 6 + script/test/TestBugPcAPI3.py | 4 + script/test/TestCalib.py | 30 + script/test/TestCameraStability1.py | 11 + script/test/TestCameraStability2.py | 14 + script/test/TestCameraStability3.py | 9 + script/test/TestCmdSynchronization.py | 32 + script/test/TestCoverDetection.py | 19 + script/test/TestEuclidean.py | 23 + script/test/TestLaserScan.py | 12 + script/test/TestLayout.py | 21 + script/test/TestMicrohawk.py | 10 + script/test/TestRecover.py | 15 + script/test/TestRelays.py | 12 + script/test/TestRemoveBackground.py | 31 + script/test/TestRobot.py | 41 + script/test/TestRobot2.py | 72 + script/test/TestRobotCmds.py | 32 + script/test/TestRobotCmds2.py | 25 + script/test/cycle_time | 4 + script/test/imgtest.py | 47 + script/test/ip | 15 + script/test/onewire.py | 122 ++ script/test/test.py | 24 + script/test/test_hexiposi.py | 8 + script/test/test_swingutils.py | 24 + script/tools/CheckPuckDetection.py | 6 + script/tools/Math.py | 68 + script/tools/RestartPuckDetection.py | 8 + script/tools/SshExec.py | 61 + script/tools/StopPuckDetection.py | 8 + 237 files changed, 18619 insertions(+) create mode 100644 config/config.properties create mode 100644 config/devices - Copy.properties create mode 100644 config/devices-modbus.properties create mode 100644 config/devices.properties create mode 100644 config/jcae.properties create mode 100644 config/mail.properties create mode 100644 config/plugins.properties create mode 100644 config/settings.properties create mode 100644 config/setup-modbus.properties create mode 100644 config/setup.properties create mode 100644 config/tasks.properties create mode 100644 devices/20161117_163816.png.properties create mode 100644 devices/A1.properties create mode 100644 devices/A2.properties create mode 100644 devices/A3.properties create mode 100644 devices/A4.properties create mode 100644 devices/A5.properties create mode 100644 devices/B1.properties create mode 100644 devices/B2.properties create mode 100644 devices/B3.properties create mode 100644 devices/B4.properties create mode 100644 devices/B5.properties create mode 100644 devices/BasePlate.properties create mode 100644 devices/C1.properties create mode 100644 devices/C2.properties create mode 100644 devices/C3.properties create mode 100644 devices/C4.properties create mode 100644 devices/C5.properties create mode 100644 devices/D1.properties create mode 100644 devices/D2.properties create mode 100644 devices/D3.properties create mode 100644 devices/D4.properties create mode 100644 devices/D5.properties create mode 100644 devices/E1.properties create mode 100644 devices/E2.properties create mode 100644 devices/E3.properties create mode 100644 devices/E4.properties create mode 100644 devices/E5.properties create mode 100644 devices/F1.properties create mode 100644 devices/F2.properties create mode 100644 devices/F3.properties create mode 100644 devices/F4.properties create mode 100644 devices/F5.properties create mode 100644 devices/Time.properties create mode 100644 devices/air_pressure.properties create mode 100644 devices/cx.properties create mode 100644 devices/cz.properties create mode 100644 devices/dewar_level.properties create mode 100644 devices/dispatcher.properties create mode 100644 devices/dp1.properties create mode 100644 devices/fx.properties create mode 100644 devices/fy.properties create mode 100644 devices/gripper_cam.properties create mode 100644 devices/img.properties create mode 100644 devices/led_ctrl.properties create mode 100644 devices/led_ctrl_1.properties create mode 100644 devices/led_ctrl_2.properties create mode 100644 devices/led_ctrl_3.properties create mode 100644 devices/led_level.properties create mode 100644 devices/m1.properties create mode 100644 devices/m2.properties create mode 100644 devices/monitoring_cam.properties create mode 100644 devices/n2_pressure.properties create mode 100644 devices/p1.properties create mode 100644 devices/phase_separator.properties create mode 100644 devices/phase_separator_level.properties create mode 100644 devices/rim_heater_temp.properties create mode 100644 devices/robot x.properties create mode 100644 devices/robot.properties create mode 100644 devices/robot_j1.properties create mode 100644 devices/robot_j2.properties create mode 100644 devices/robot_j3.properties create mode 100644 devices/robot_j4.properties create mode 100644 devices/robot_j5.properties create mode 100644 devices/robot_j6.properties create mode 100644 devices/robot_modbus.properties create mode 100644 devices/robot_rx.properties create mode 100644 devices/robot_ry.properties create mode 100644 devices/robot_rz.properties create mode 100644 devices/robot_x.properties create mode 100644 devices/robot_y.properties create mode 100644 devices/robot_z.properties create mode 100644 devices/ry.properties create mode 100644 devices/smart_magnet.properties create mode 100644 devices/smc_current.properties create mode 100644 devices/smc_current_rb.properties create mode 100644 devices/src1.properties create mode 100644 devices/src2.properties create mode 100644 devices/top_cam.properties create mode 100644 devices/ue.properties create mode 100644 devices/wago.properties create mode 100644 plugins/BarcodeReaderPanel.form create mode 100644 plugins/BarcodeReaderPanel.java create mode 100644 plugins/Beeper.java create mode 100644 plugins/Commands.form create mode 100644 plugins/Commands.java create mode 100644 plugins/Hexiposi.form create mode 100644 plugins/Hexiposi.java create mode 100644 plugins/HexiposiPanel.form create mode 100644 plugins/HexiposiPanel.java create mode 100644 plugins/LN2.form create mode 100644 plugins/LN2.java create mode 100644 plugins/LaserUE.java create mode 100644 plugins/LaserUEPanel.form create mode 100644 plugins/LaserUEPanel.java create mode 100644 plugins/MXSC-1.10.0.jar create mode 100644 plugins/MXSC-1.10.0.jar.back create mode 100644 plugins/MjpegSource2.java create mode 100644 plugins/NewJPanel.form create mode 100644 plugins/NewJPanel.java create mode 100644 plugins/PuckDetectionPanel.form create mode 100644 plugins/PuckDetectionPanel.java create mode 100644 plugins/Recovery.form create mode 100644 plugins/Recovery.java create mode 100644 plugins/RobotModbus.java create mode 100644 plugins/RobotPanel.form create mode 100644 plugins/RobotPanel.java create mode 100644 plugins/RobotTcp.java create mode 100644 plugins/SmartMagnetConfig.java create mode 100644 plugins/SmartMagnetPanel.form create mode 100644 plugins/SmartMagnetPanel.java create mode 100644 plugins/TestZMQ.java create mode 100644 plugins/WagoPanel.form create mode 100644 plugins/WagoPanel.java create mode 100644 plugins/gui.form create mode 100644 plugins/gui.java create mode 100644 script/LN2_Monitoring.scd create mode 100644 script/LevelMonitoring.scd create mode 100644 script/calibration/BinarySearchYZ.py create mode 100644 script/calibration/HillClimbingXZ.py create mode 100644 script/calibration/ScanRZ.py create mode 100644 script/calibration/ScanX.py create mode 100644 script/calibration/ScanY.py create mode 100644 script/calibration/ScanYZ.py create mode 100644 script/calibration/ToolCalibration.py create mode 100644 script/calibration/ToolCalibration2.py create mode 100644 script/calibration/ToolCalibration3.py create mode 100644 script/client/PShellClient.py create mode 100644 script/client/TellClient.py create mode 100644 script/client/sseclient.py create mode 100644 script/client/tell.py create mode 100644 script/data/get_samples_info.py create mode 100644 script/data/pucks.py create mode 100644 script/data/samples.py create mode 100644 script/data/set_samples_info.py create mode 100644 script/devices/BarcodeReader.py create mode 100644 script/devices/Gonio.py create mode 100644 script/devices/Hexiposi.py create mode 100644 script/devices/LaserDistance.py create mode 100644 script/devices/LedCtrl.py create mode 100644 script/devices/OneWire.py create mode 100644 script/devices/RobotModbus.py create mode 100644 script/devices/RobotMotors.py create mode 100644 script/devices/RobotSC.py create mode 100644 script/devices/RobotTCP.py create mode 100644 script/devices/SmartMagnet.py create mode 100644 script/devices/Wago.py create mode 100644 script/hexiposi_positon.scd create mode 100644 script/imgproc/CameraCalibration.py create mode 100644 script/imgproc/CoverDetection.py create mode 100644 script/imgproc/CoverDetectionCalibration.py create mode 100644 script/imgproc/CreateMask.py create mode 100644 script/imgproc/LedDetectionFilter.py create mode 100644 script/imgproc/LedDetectionProc.py create mode 100644 script/imgproc/Utils.py create mode 100644 script/local.groovy create mode 100644 script/local.js create mode 100644 script/local.py create mode 100644 script/motion/calibrate_tool.py create mode 100644 script/motion/dry.py create mode 100644 script/motion/get_aux.py create mode 100644 script/motion/get_dewar.py create mode 100644 script/motion/get_gonio.py create mode 100644 script/motion/homing_hexiposi.py create mode 100644 script/motion/mount.py create mode 100644 script/motion/move_aux.py create mode 100644 script/motion/move_cold.py create mode 100644 script/motion/move_dewar.py create mode 100644 script/motion/move_gonio.py create mode 100644 script/motion/move_heater.py create mode 100644 script/motion/move_home.py create mode 100644 script/motion/move_park.py create mode 100644 script/motion/move_scanner.py create mode 100644 script/motion/put_aux.py create mode 100644 script/motion/put_dewar.py create mode 100644 script/motion/put_gonio.py create mode 100644 script/motion/recover.py create mode 100644 script/motion/robot_recover.py create mode 100644 script/motion/scan_pin.py create mode 100644 script/motion/tools.py create mode 100644 script/motion/trash.py create mode 100644 script/motion/unmount.py create mode 100644 script/setup/ExposureScan.py create mode 100644 script/setup/Layout.py create mode 100644 script/tasks/LedMonitoring.py create mode 100644 script/test/CameraCalibration.py create mode 100644 script/test/CoverDetection.py create mode 100644 script/test/PuckDetection.py create mode 100644 script/test/PuckDetectionTest.py create mode 100644 script/test/RobotCartesianScan.py create mode 100644 script/test/SampleDataInput.py create mode 100644 script/test/SampleDataInput_Dominik.py create mode 100644 script/test/SampleDetection.py create mode 100644 script/test/TestAlign.py create mode 100644 script/test/TestBugPcAPI create mode 100644 script/test/TestBugPcAPI.py create mode 100644 script/test/TestBugPcAPI2.py create mode 100644 script/test/TestBugPcAPI3.py create mode 100644 script/test/TestCalib.py create mode 100644 script/test/TestCameraStability1.py create mode 100644 script/test/TestCameraStability2.py create mode 100644 script/test/TestCameraStability3.py create mode 100644 script/test/TestCmdSynchronization.py create mode 100644 script/test/TestCoverDetection.py create mode 100644 script/test/TestEuclidean.py create mode 100644 script/test/TestLaserScan.py create mode 100644 script/test/TestLayout.py create mode 100644 script/test/TestMicrohawk.py create mode 100644 script/test/TestRecover.py create mode 100644 script/test/TestRelays.py create mode 100644 script/test/TestRemoveBackground.py create mode 100644 script/test/TestRobot.py create mode 100644 script/test/TestRobot2.py create mode 100644 script/test/TestRobotCmds.py create mode 100644 script/test/TestRobotCmds2.py create mode 100644 script/test/cycle_time create mode 100644 script/test/imgtest.py create mode 100644 script/test/ip create mode 100644 script/test/onewire.py create mode 100644 script/test/test.py create mode 100644 script/test/test_hexiposi.py create mode 100644 script/test/test_swingutils.py create mode 100644 script/tools/CheckPuckDetection.py create mode 100644 script/tools/Math.py create mode 100644 script/tools/RestartPuckDetection.py create mode 100644 script/tools/SshExec.py create mode 100644 script/tools/StopPuckDetection.py diff --git a/config/config.properties b/config/config.properties new file mode 100644 index 0000000..8af449a --- /dev/null +++ b/config/config.properties @@ -0,0 +1,32 @@ +#Thu Feb 14 10:43:15 CET 2019 +autoSaveScanData=true +commandExecutionEvents=false +createSessionFiles=true +dataLayout=default +dataPath={data}/{year}_{month}/{date}/{date}_{time}_{name} +dataProvider=h5 +dataScanFlushRecords=true +dataScanPreserveTypes=false +dataScanReleaseRecords=false +dataServerPort=-1 +depthDimension=0 +hostName=null +instanceName=MXSC +logDaysToLive=30 +logLevel=Fine +logLevelConsole=Off +logPath={logs}/{date}_{time} +notificationLevel=null +saveCommandStatistics=false +scanStreamerPort=-1 +serverEnabled=true +serverPort=8080 +simulation=false +terminalEnabled=false +terminalPort=3579 +userAuthenticator= +userManagement=false +versionTrackingEnabled=true +versionTrackingLogin={context}/svcusr-hlapp_robot +versionTrackingManual=false +versionTrackingRemote=git@git.psi.ch\:tell/SwissMX.git diff --git a/config/devices - Copy.properties b/config/devices - Copy.properties new file mode 100644 index 0000000..cc3672f --- /dev/null +++ b/config/devices - Copy.properties @@ -0,0 +1,67 @@ +img=ch.psi.pshell.prosilica.Prosilica|25001 "PacketSize=1522;PixelFormat=Mono8;BinningX=1;BinningY=1;RegionX=300;RegionY=200;Width=1000;Height=1000"|||false +gripper_cam=ch.psi.pshell.imaging.MjpegSource|http://129.129.110.114/axis-cgi/mjpg/video.cgi||-1000| +microscan=ch.psi.pshell.serial.TcpDevice|129.129.100.200:2001||| +microscan_cmd=ch.psi.pshell.serial.TcpDevice|129.129.100.200:2003||| +ue=LaserUE|COM4|||false +#robot=RobotTcp|127.0.0.1:1000||| +#onewire=ch.psi.pshell.serial.TcpDevice|129.129.126.83:5000||| +puck_detection=ch.psi.mxsc.PuckDetection|tell-raspberrypi:5556||| +#robot_modbus=ch.psi.pshell.modbus.ModbusTCP|129.129.126.100:502||| +#jf1=ch.psi.pshell.modbus.AnalogInput|robot_modbus 0||100| +#jf2=ch.psi.pshell.modbus.AnalogInput|robot_modbus 1||100| +#jf3=ch.psi.pshell.modbus.AnalogInput|robot_modbus 2||100| +#jf4=ch.psi.pshell.modbus.AnalogInput|robot_modbus 3||100| +#jf5=ch.psi.pshell.modbus.AnalogInput|robot_modbus 4||100| +#jf6=ch.psi.pshell.modbus.AnalogInput|robot_modbus 5||100| +#robot_sts=ch.psi.pshell.modbus.AnalogInputArray|robot_modbus 6 6||100| +#robot_cmd=ch.psi.pshell.modbus.AnalogOutput|robot_modbus 12||| +#robot_args=ch.psi.pshell.modbus.AnalogOutputArray|robot_modbus 47 12||| +#robot_req=ch.psi.pshell.modbus.AnalogOutput|robot_modbus 13||| +#robot_ack=ch.psi.pshell.modbus.AnalogInput|robot_modbus 14||| +#robot_ret=ch.psi.pshell.modbus.AnalogInputArray|robot_modbus 15 12||| +#wago_back=ch.psi.pshell.modbus.ModbusTCP|SF-TEST-WAGO1:502||| +wago=ch.psi.pshell.modbus.ModbusTCP|wago-mxsc-1:502||| +led_ok_1=ch.psi.pshell.modbus.DigitalInput|wago 0||1000| +led_ok_2=ch.psi.pshell.modbus.DigitalInput|wago 1||1000| +led_ok_3=ch.psi.pshell.modbus.DigitalInput|wago 2||1000| +feedback_local_safety=ch.psi.pshell.modbus.DigitalInput|wago 3||1000| +feedback_psys_safety=ch.psi.pshell.modbus.DigitalInput|wago 4||1000| +filling_phase_separator=ch.psi.pshell.modbus.DigitalInput|wago 5||1000| +filling_dewar=ch.psi.pshell.modbus.DigitalInput|wago 6||1000| +dewar_level_high_alarm=ch.psi.pshell.modbus.DigitalInput|wago 7||1000| +guiding_tool_park=ch.psi.pshell.modbus.DigitalInput|wago 8||1000| +air_pressure_ok=ch.psi.pshell.modbus.DigitalInput|wago 9||1000|false +n2_pressure_ok=ch.psi.pshell.modbus.DigitalInput|wago 10||1000| +he_chamber_valve_1=ch.psi.pshell.modbus.DigitalInput|wago 15||1000| +he_chamber_valve_2=ch.psi.pshell.modbus.DigitalInput|wago 16||1000| +relays=ch.psi.pshell.modbus.DigitalOutputArray|wago 0 16||1000| +release_local_safety=ch.psi.pshell.modbus.DigitalOutput|wago 0||| +release_psys_safety=ch.psi.pshell.modbus.DigitalOutput|wago 1||| +ln2_main_power=ch.psi.pshell.modbus.DigitalOutput|wago 2||| +rim_heater=ch.psi.pshell.modbus.DigitalOutput|wago 3||| +phase_separator_ln2=ch.psi.pshell.modbus.DigitalOutput|wago 4||| +dewar_ln2=ch.psi.pshell.modbus.DigitalOutput|wago 5|||false +valve_he_chamber=ch.psi.pshell.modbus.DigitalOutput|wago 6||| +gripper_dryer=ch.psi.pshell.modbus.DigitalOutput|wago 7||| +valve_1=ch.psi.pshell.modbus.DigitalOutput|wago 8||| +valve_2=ch.psi.pshell.modbus.DigitalOutput|wago 9||| +valve_3=ch.psi.pshell.modbus.DigitalOutput|wago 10||| +valve_4=ch.psi.pshell.modbus.DigitalOutput|wago 11||| +#spare_do_1=ch.psi.pshell.modbus.DigitalOutput|wago 12||| +#spare_do_2=ch.psi.pshell.modbus.DigitalOutput|wago 13||| +#spare_do_3=ch.psi.pshell.modbus.DigitalOutput|wago 14||| +#spare_do_4=ch.psi.pshell.modbus.DigitalOutput|wago 15||| +phase_separator_level=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 0||10000| +dewar_level=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 1||10000| +rim_heater_temp=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 2||10000| +air_pressure=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 3||10000| +n2_pressure=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 4||10000| +#spare_ai_1=ch.psi.pshell.modbus.AnalogInput|wago 5||| +#spare_ai_2=ch.psi.pshell.modbus.AnalogInput|wago 6||| +#spare_ai_3=ch.psi.pshell.modbus.AnalogInput|wago 7||| +led_ctrl_1=ch.psi.pshell.modbus.ProcessVariable|wago 0||| +led_ctrl_2=ch.psi.pshell.modbus.ProcessVariable|wago 1||| +led_ctrl_3=ch.psi.pshell.modbus.ProcessVariable|wago 2||| +#spare_ao_3=ch.psi.pshell.modbus.AnalogOutput|wago 3||| +#cam=ch.psi.pshell.epics.AreaDetector|MX-SAMCAM||| +#img_back=ch.psi.pshell.imaging.CameraSource|cam||-100| diff --git a/config/devices-modbus.properties b/config/devices-modbus.properties new file mode 100644 index 0000000..d46c089 --- /dev/null +++ b/config/devices-modbus.properties @@ -0,0 +1,50 @@ +wago=ch.psi.pshell.modbus.ModbusTCP|wago-mxsc-1:502||| +led_ok_1=ch.psi.pshell.modbus.DigitalInput|wago 0||1000| +led_ok_2=ch.psi.pshell.modbus.DigitalInput|wago 1||1000| +led_ok_3=ch.psi.pshell.modbus.DigitalInput|wago 2||1000| +feedback_local_safety=ch.psi.pshell.modbus.DigitalInput|wago 3||1000| +feedback_psys_safety=ch.psi.pshell.modbus.DigitalInput|wago 4||1000| +filling_phase_separator=ch.psi.pshell.modbus.DigitalInput|wago 5||1000| +filling_dewar=ch.psi.pshell.modbus.DigitalInput|wago 6||1000| +dewar_level_high_alarm=ch.psi.pshell.modbus.DigitalInput|wago 7||1000| +guiding_tool_park=ch.psi.pshell.modbus.DigitalInput|wago 8||1000| +air_pressure_ok=ch.psi.pshell.modbus.DigitalInput|wago 9||1000|false +n2_pressure_ok=ch.psi.pshell.modbus.DigitalInput|wago 10||1000| +#spare_di_1=ch.psi.pshell.modbus.DigitalInput|wago 11||| +#spare_di_2=ch.psi.pshell.modbus.DigitalInput|wago 12||| +#spare_di_3=ch.psi.pshell.modbus.DigitalInput|wago 13||| +#spare_di_4=ch.psi.pshell.modbus.DigitalInput|wago 14||| +he_chamber_valve_1=ch.psi.pshell.modbus.DigitalInput|wago 15||1000| +he_chamber_valve_2=ch.psi.pshell.modbus.DigitalInput|wago 16||1000| +smc_magnet_status=ch.psi.pshell.modbus.DigitalInput|wago 17||1000| +smc_mounted_1=ch.psi.pshell.modbus.DigitalInput|wago 18||1000| +smc_mounted_2=ch.psi.pshell.modbus.DigitalInput|wago 19||1000| +relays=ch.psi.pshell.modbus.DigitalOutputArray|wago 0 16||1000| +release_local_safety=ch.psi.pshell.modbus.DigitalOutput|wago 0||| +release_psys_safety=ch.psi.pshell.modbus.DigitalOutput|wago 1||| +ln2_main_power=ch.psi.pshell.modbus.DigitalOutput|wago 2||| +rim_heater=ch.psi.pshell.modbus.DigitalOutput|wago 3||| +phase_separator_ln2=ch.psi.pshell.modbus.DigitalOutput|wago 4||| +dewar_ln2=ch.psi.pshell.modbus.DigitalOutput|wago 5|||false +valve_he_chamber=ch.psi.pshell.modbus.DigitalOutput|wago 6||| +gripper_dryer=ch.psi.pshell.modbus.DigitalOutput|wago 7||| +valve_1=ch.psi.pshell.modbus.DigitalOutput|wago 8||| +valve_2=ch.psi.pshell.modbus.DigitalOutput|wago 9||| +valve_3=ch.psi.pshell.modbus.DigitalOutput|wago 10||| +valve_4=ch.psi.pshell.modbus.DigitalOutput|wago 11||| +#spare_do_1=ch.psi.pshell.modbus.DigitalOutput|wago 12||| +smc_sup_det=ch.psi.pshell.modbus.DigitalOutput|wago 13||| +#spare_do_3=ch.psi.pshell.modbus.DigitalOutput|wago 14||| +#spare_do_4=ch.psi.pshell.modbus.DigitalOutput|wago 15||| +phase_separator_level=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 0||10000| +dewar_level=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 1||10000| +rim_heater_temp=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 2||10000| +#spare_ai_1=ch.psi.pshell.modbus.AnalogInput|wago 3|||true +smc_current_rb=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 4||1000| +#spare_ai_3=ch.psi.pshell.modbus.AnalogInput|wago 5||| +#spare_ai_4=ch.psi.pshell.modbus.AnalogInput|wago 6||| +#spare_ai_5=ch.psi.pshell.modbus.AnalogInput|wago 7||| +led_ctrl_1=ch.psi.pshell.modbus.ProcessVariable|wago 0||| +led_ctrl_2=ch.psi.pshell.modbus.ProcessVariable|wago 1||| +led_ctrl_3=ch.psi.pshell.modbus.ProcessVariable|wago 2||| +smc_current=ch.psi.pshell.modbus.ProcessVariable|wago 3||| diff --git a/config/devices.properties b/config/devices.properties new file mode 100644 index 0000000..61a1f7c --- /dev/null +++ b/config/devices.properties @@ -0,0 +1,80 @@ +#img=ch.psi.pshell.prosilica.Prosilica|25001 "PacketSize=1522;PixelFormat=Mono8;BinningX=1;BinningY=1;RegionX=300;RegionY=200;Width=1000;Height=1000;MulticastEnable=Off"|||false +$gripper_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=1 reopen||-200| +monitoring_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=2 reopen||-200| +top_cam=ch.psi.pshell.imaging.MjpegSource|http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi?camera=3 true||-200| +#cam=ch.psi.pshell.epics.AreaDetector|MX-SAMCAM||| +microscan=ch.psi.pshell.serial.TcpDevice|MicroHAWK38C528:2001||| +microscan_cmd=ch.psi.pshell.serial.TcpDevice|MicroHAWK38C528:2003||| +ue=LaserUE|COM4|||false +puck_detection=ch.psi.mxsc.PuckDetection|tell-raspberrypi:5556||| +#onewire=ch.psi.pshell.serial.TcpDevice|129.129.126.83:5000||| +#robot=RobotTcp|127.0.0.1:1000||| +#robot_modbus=ch.psi.pshell.modbus.ModbusTCP|129.129.126.100:502||| +#jf1=ch.psi.pshell.modbus.AnalogInput|robot_modbus 0||100| +#jf2=ch.psi.pshell.modbus.AnalogInput|robot_modbus 1||100| +#jf3=ch.psi.pshell.modbus.AnalogInput|robot_modbus 2||100| +#jf4=ch.psi.pshell.modbus.AnalogInput|robot_modbus 3||100| +#jf5=ch.psi.pshell.modbus.AnalogInput|robot_modbus 4||100| +#jf6=ch.psi.pshell.modbus.AnalogInput|robot_modbus 5||100| +#robot_sts=ch.psi.pshell.modbus.AnalogInputArray|robot_modbus 6 6||100| +#robot_cmd=ch.psi.pshell.modbus.AnalogOutput|robot_modbus 12||| +#robot_args=ch.psi.pshell.modbus.AnalogOutputArray|robot_modbus 47 12||| +#robot_req=ch.psi.pshell.modbus.AnalogOutput|robot_modbus 13||| +#robot_ack=ch.psi.pshell.modbus.AnalogInput|robot_modbus 14||| +#robot_ret=ch.psi.pshell.modbus.AnalogInputArray|robot_modbus 15 12||| +wago=ch.psi.pshell.modbus.ModbusTCP|wago-mxsc-1:502||| +led_ok_1=ch.psi.pshell.modbus.DigitalInput|wago 0||1000| +led_ok_2=ch.psi.pshell.modbus.DigitalInput|wago 1||1000| +led_ok_3=ch.psi.pshell.modbus.DigitalInput|wago 2||1000| +feedback_local_safety=ch.psi.pshell.modbus.DigitalInput|wago 3||1000| +feedback_psys_safety=ch.psi.pshell.modbus.DigitalInput|wago 4||1000| +filling_phase_separator=ch.psi.pshell.modbus.DigitalInput|wago 5||1000| +filling_dewar=ch.psi.pshell.modbus.DigitalInput|wago 6||1000| +dewar_level_high_alarm=ch.psi.pshell.modbus.DigitalInput|wago 7||1000| +guiding_tool_park=ch.psi.pshell.modbus.DigitalInput|wago 8||1000| +air_pressure_ok=ch.psi.pshell.modbus.DigitalInput|wago 9||1000|false +n2_pressure_ok=ch.psi.pshell.modbus.DigitalInput|wago 10||1000| +gripperID_LSB=ch.psi.pshell.modbus.DigitalInput|wago 11||1000| +gripperID_=ch.psi.pshell.modbus.DigitalInput|wago 12||1000| +gripperID_MSB=ch.psi.pshell.modbus.DigitalInput|wago 13||1000| +RT_gripper_open=ch.psi.pshell.modbus.DigitalInput|wago 14||1000| +RT_gripper_close\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020\u0020RT_gripper_close=ch.psi.pshell.modbus.DigitalInput|wago 15||1000| +RT_sample_detection=ch.psi.pshell.modbus.DigitalInput|wago 16||1000| +smc_magnet_status=ch.psi.pshell.modbus.DigitalInput|wago 17||1000| +smc_mounted_1=ch.psi.pshell.modbus.DigitalInput|wago 18||1000| +smc_mounted_2=ch.psi.pshell.modbus.DigitalInput|wago 19||1000| +relays=ch.psi.pshell.modbus.DigitalOutputArray|wago 0 16||1000| +release_local_safety=ch.psi.pshell.modbus.DigitalOutput|wago 0||| +release_psys_safety=ch.psi.pshell.modbus.DigitalOutput|wago 1||| +ln2_main_power=ch.psi.pshell.modbus.DigitalOutput|wago 2||| +rim_heater=ch.psi.pshell.modbus.DigitalOutput|wago 3||| +phase_separator_ln2=ch.psi.pshell.modbus.DigitalOutput|wago 4||| +dewar_ln2=ch.psi.pshell.modbus.DigitalOutput|wago 5|||false +valve_he_chamber=ch.psi.pshell.modbus.DigitalOutput|wago 6||| +gripper_dryer=ch.psi.pshell.modbus.DigitalOutput|wago 7||1000| +valve_1=ch.psi.pshell.modbus.DigitalOutput|wago 8||| +valve_2=ch.psi.pshell.modbus.DigitalOutput|wago 9||| +valve_3=ch.psi.pshell.modbus.DigitalOutput|wago 10||| +valve_4=ch.psi.pshell.modbus.DigitalOutput|wago 11||| +#spare_do_1=ch.psi.pshell.modbus.DigitalOutput|wago 12||| +smc_sup_det=ch.psi.pshell.modbus.DigitalOutput|wago 13||| +#spare_do_3=ch.psi.pshell.modbus.DigitalOutput|wago 14||| +#spare_do_4=ch.psi.pshell.modbus.DigitalOutput|wago 15||| +phase_separator_level=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 0||10000| +dewar_level=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 1||10000| +rim_heater_temp=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 2||10000| +#spare_ai_1=ch.psi.pshell.modbus.AnalogInput|wago 3|||true +smc_current_rb=ch.psi.pshell.modbus.ReadonlyProcessVariable|wago 4||1000| +#spare_ai_3=ch.psi.pshell.modbus.AnalogInput|wago 5||| +#spare_ai_4=ch.psi.pshell.modbus.AnalogInput|wago 6||| +#spare_ai_5=ch.psi.pshell.modbus.AnalogInput|wago 7||| +led_ctrl_1=ch.psi.pshell.modbus.ProcessVariable|wago 0||| +led_ctrl_2=ch.psi.pshell.modbus.ProcessVariable|wago 1||| +led_ctrl_3=ch.psi.pshell.modbus.ProcessVariable|wago 2||| +smc_current=ch.psi.pshell.modbus.ProcessVariable|wago 3||| +#img_back=ch.psi.pshell.imaging.CameraSource|cam||-100| +#fx=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_FX|||true +#fy=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_FY|||true +#ry=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_ROT_Y|||true +#cz=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_CZ|||true +#cx=ch.psi.pshell.epics.Motor|SAR-EXPMX:MOT_CX|||true diff --git a/config/jcae.properties b/config/jcae.properties new file mode 100644 index 0000000..2bb0691 --- /dev/null +++ b/config/jcae.properties @@ -0,0 +1,11 @@ +#Tue Sep 06 15:10:24 CEST 2016 +ch.psi.jcae.ContextFactory.addressList= +ch.psi.jcae.ContextFactory.serverPort= +ch.psi.jcae.ContextFactory.maxArrayBytes=20000000 +ch.psi.jcae.ChannelFactory.retries=1 +ch.psi.jcae.ChannelFactory.timeout=500 +ch.psi.jcae.impl.DefaultChannelService.retries=2 +ch.psi.jcae.impl.DefaultChannelService.timeout=1000 +ch.psi.jcae.ContextFactory.autoAddressList=true +ch.psi.jcae.ContextFactory.useShellVariables=false +ch.psi.jcae.ContextFactory.addLocalBroadcastInterfaces=false diff --git a/config/mail.properties b/config/mail.properties new file mode 100644 index 0000000..e04b672 --- /dev/null +++ b/config/mail.properties @@ -0,0 +1,9 @@ +#Mon Oct 23 10:53:54 CEST 2017 +auth=None +from= +host= +port=0 +pwd= +smsSuffix=@sms.switch.ch +to= +usr= diff --git a/config/plugins.properties b/config/plugins.properties new file mode 100644 index 0000000..1568671 --- /dev/null +++ b/config/plugins.properties @@ -0,0 +1,21 @@ +Commands.java=disabled +Recovery.java=disabled +MXSC-1.10.0.jar=enabled +WagoPanel.java=enabled +LaserUEPanel.java=enabled +BarcodeReaderPanel.java=enabled +PuckDetectionPanel.java=enabled +HexiposiPanel.java=enabled +MjpegSource2.java=enabled +LN2.java=disabled +Hexiposi.java=disabled +NewJPanel.java=disabled +RobotPanel.java=enabled +SmartMagnetConfig.java=disabled +SmartMagnetPanel.java=enabled +LaserUE.java=enabled +TestZMQ.java=disabled +RobotModbus.java=disabled +RobotTcp.java=disabled +Beeper.java=disabled +gui.java=disabled diff --git a/config/settings.properties b/config/settings.properties new file mode 100644 index 0000000..ee05755 --- /dev/null +++ b/config/settings.properties @@ -0,0 +1,17 @@ +#Thu Feb 14 10:47:31 CET 2019 +barcode_reader_scan_pucks=true +dry_mount_counter=0 +dry_timestamp=1.543854393748E9 +force_dry_mount_count=0 +force_dry_timeout=0 +imaging_enabled=false +led_level=0.0 +mounted_sample_position= +pin_angle_offset=0.0 +pin_offset=0.0 +puck_types=true +roi_h=1000 +roi_w=1000 +roi_x=337 +roi_y=139 +room_temperature_enabled=false diff --git a/config/setup-modbus.properties b/config/setup-modbus.properties new file mode 100644 index 0000000..eb292c1 --- /dev/null +++ b/config/setup-modbus.properties @@ -0,0 +1,18 @@ +#Wed Sep 14 15:16:45 CEST 2016 +configFile={config}/config.properties +configFileDevices={config}/devices-modbus.properties +configFilePlugins={config}/plugins.properties +configFileTasks={config}/tasks.properties +configPath={home}/config +contextPath={outp}/context +dataPath={outp}/data +devicesPath={home}/devices +extensionsPath={home}/extensions +imagesPath={outp}/images +libraryPath={script}; {script}/Lib +logPath={outp}/log +pluginsPath={home}/plugins +scriptPath={home}/script +scriptType=py +sessionsPath={outp}/sessions +wwwPath={home}/www diff --git a/config/setup.properties b/config/setup.properties new file mode 100644 index 0000000..292e9b2 --- /dev/null +++ b/config/setup.properties @@ -0,0 +1,19 @@ +#Thu Feb 14 09:08:25 CET 2019 +configFile={config}/config.properties +configFileDevices={config}/devices.properties +configFilePlugins={config}/plugins.properties +configFileSettings={config}/settings.properties +configFileTasks={config}/tasks.properties +configPath={home}/config +contextPath={outp}/context +dataPath={outp}/data +devicesPath={home}/devices +extensionsPath={home}/extensions +imagesPath={outp}/images +libraryPath={script}; {script}/Lib +logPath={outp}/log +pluginsPath={home}/plugins +scriptPath={home}/script +scriptType=py +sessionsPath={outp}/sessions +wwwPath={home}/www diff --git a/config/tasks.properties b/config/tasks.properties new file mode 100644 index 0000000..e291198 --- /dev/null +++ b/config/tasks.properties @@ -0,0 +1 @@ +tasks/LedMonitoring=120 diff --git a/devices/20161117_163816.png.properties b/devices/20161117_163816.png.properties new file mode 100644 index 0000000..be1fd91 --- /dev/null +++ b/devices/20161117_163816.png.properties @@ -0,0 +1,20 @@ +#Mon Oct 23 15:10:20 CEST 2017 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/A1.properties b/devices/A1.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/A1.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/A2.properties b/devices/A2.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/A2.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/A3.properties b/devices/A3.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/A3.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/A4.properties b/devices/A4.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/A4.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/A5.properties b/devices/A5.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/A5.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/B1.properties b/devices/B1.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/B1.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/B2.properties b/devices/B2.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/B2.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/B3.properties b/devices/B3.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/B3.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/B4.properties b/devices/B4.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/B4.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/B5.properties b/devices/B5.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/B5.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/BasePlate.properties b/devices/BasePlate.properties new file mode 100644 index 0000000..1e25f83 --- /dev/null +++ b/devices/BasePlate.properties @@ -0,0 +1 @@ +#Fri Feb 10 14:35:38 CET 2017 diff --git a/devices/C1.properties b/devices/C1.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/C1.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/C2.properties b/devices/C2.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/C2.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/C3.properties b/devices/C3.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/C3.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/C4.properties b/devices/C4.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/C4.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/C5.properties b/devices/C5.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/C5.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/D1.properties b/devices/D1.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/D1.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/D2.properties b/devices/D2.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/D2.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/D3.properties b/devices/D3.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/D3.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/D4.properties b/devices/D4.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/D4.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/D5.properties b/devices/D5.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/D5.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/E1.properties b/devices/E1.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/E1.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/E2.properties b/devices/E2.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/E2.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/E3.properties b/devices/E3.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/E3.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/E4.properties b/devices/E4.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/E4.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/E5.properties b/devices/E5.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/E5.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/F1.properties b/devices/F1.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/F1.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/F2.properties b/devices/F2.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/F2.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/F3.properties b/devices/F3.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/F3.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/F4.properties b/devices/F4.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/F4.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/F5.properties b/devices/F5.properties new file mode 100644 index 0000000..7bb91cd --- /dev/null +++ b/devices/F5.properties @@ -0,0 +1,3 @@ +#Thu Feb 14 10:34:24 CET 2019 +detection=Both +disabled=false diff --git a/devices/Time.properties b/devices/Time.properties new file mode 100644 index 0000000..33011f0 --- /dev/null +++ b/devices/Time.properties @@ -0,0 +1,10 @@ +#Wed Jun 27 10:48:14 CEST 2018 +maxValue=NaN +minValue=NaN +offset=0.0 +precision=-1 +resolution=NaN +rotation=false +scale=1.0 +sign_bit=0 +unit=null diff --git a/devices/air_pressure.properties b/devices/air_pressure.properties new file mode 100644 index 0000000..e476b09 --- /dev/null +++ b/devices/air_pressure.properties @@ -0,0 +1,5 @@ +#Thu Mar 01 11:13:34 CET 2018 +offset=0.0 +precision=-1 +scale=1.0 +unit=null diff --git a/devices/cx.properties b/devices/cx.properties new file mode 100644 index 0000000..1720045 --- /dev/null +++ b/devices/cx.properties @@ -0,0 +1,17 @@ +#Fri Aug 10 15:47:53 CEST 2018 +defaultSpeed=2.0 +estbilizationDelay=0 +hasEnable=false +homingType=None +maxSpeed=NaN +maxValue=0.0 +minSpeed=NaN +minValue=0.0 +offset=0.0 +precision=3 +resolution=0.001 +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/cz.properties b/devices/cz.properties new file mode 100644 index 0000000..b8877dd --- /dev/null +++ b/devices/cz.properties @@ -0,0 +1,17 @@ +#Fri Aug 10 15:47:15 CEST 2018 +defaultSpeed=2.0 +estbilizationDelay=0 +hasEnable=false +homingType=None +maxSpeed=NaN +maxValue=0.0 +minSpeed=NaN +minValue=0.0 +offset=0.0 +precision=3 +resolution=0.001 +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/dewar_level.properties b/devices/dewar_level.properties new file mode 100644 index 0000000..38fab62 --- /dev/null +++ b/devices/dewar_level.properties @@ -0,0 +1,6 @@ +#Wed Aug 08 14:23:54 CEST 2018 +offset=-25.81632 +precision=2 +scale=0.003888 +sign_bit=0 +unit=% diff --git a/devices/dispatcher.properties b/devices/dispatcher.properties new file mode 100644 index 0000000..5a3e672 --- /dev/null +++ b/devices/dispatcher.properties @@ -0,0 +1,11 @@ +#Thu May 03 11:54:38 CEST 2018 +disableCompression=false +keepListeningOnStop=false +mappingIncomplete=null +parallelHandlerProcessing=true +sendAwaitFirstMessage=false +sendBuildChannelConfig=null +sendStrategy=null +sendSyncTimeout=0 +socketType=DEFAULT +validationInconsistency=null diff --git a/devices/dp1.properties b/devices/dp1.properties new file mode 100644 index 0000000..c853c11 --- /dev/null +++ b/devices/dp1.properties @@ -0,0 +1,11 @@ +#Fri Jul 08 10:53:26 CEST 2016 +motor1=0.0|4.0|8.0|0.0 +motor2=0.0|5.0|3.0|NaN +motor3=null +motor4=null +motor5=null +motor6=null +motor7=null +motor8=null +positions=Park|Ready|Out|Clear +precision=-1 diff --git a/devices/fx.properties b/devices/fx.properties new file mode 100644 index 0000000..44a1a35 --- /dev/null +++ b/devices/fx.properties @@ -0,0 +1,17 @@ +#Fri Aug 10 15:47:14 CEST 2018 +defaultSpeed=2.0 +estbilizationDelay=0 +hasEnable=false +homingType=None +maxSpeed=NaN +maxValue=0.0 +minSpeed=NaN +minValue=0.0 +offset=0.0 +precision=3 +resolution=0.001 +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/fy.properties b/devices/fy.properties new file mode 100644 index 0000000..44a1a35 --- /dev/null +++ b/devices/fy.properties @@ -0,0 +1,17 @@ +#Fri Aug 10 15:47:14 CEST 2018 +defaultSpeed=2.0 +estbilizationDelay=0 +hasEnable=false +homingType=None +maxSpeed=NaN +maxValue=0.0 +minSpeed=NaN +minValue=0.0 +offset=0.0 +precision=3 +resolution=0.001 +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=mm diff --git a/devices/gripper_cam.properties b/devices/gripper_cam.properties new file mode 100644 index 0000000..6fc903f --- /dev/null +++ b/devices/gripper_cam.properties @@ -0,0 +1,20 @@ +#Thu Jun 28 17:46:46 CEST 2018 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/img.properties b/devices/img.properties new file mode 100644 index 0000000..9dffde8 --- /dev/null +++ b/devices/img.properties @@ -0,0 +1,24 @@ +#Wed Sep 12 14:06:31 CEST 2018 +colormap=Grayscale +colormapAutomatic=false +colormapMax=18.133 +colormapMin=6.4 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=899 +roiWidth=893 +roiX=48 +roiY=45 +rotation=230.05382605006437 +rotationCrop=true +scale=1.0 +spatialCalOffsetX=-447.0 +spatialCalOffsetY=-450.0 +spatialCalScaleX=0.5262180258614136 +spatialCalScaleY=0.5227145226413789 +spatialCalUnits=mm +transpose=false diff --git a/devices/led_ctrl.properties b/devices/led_ctrl.properties new file mode 100644 index 0000000..00dcc48 --- /dev/null +++ b/devices/led_ctrl.properties @@ -0,0 +1,8 @@ +#Tue Jun 20 15:07:30 CEST 2017 +maxValue=0.4 +minValue=0.0 +offset=0.0 +precision=2 +resolution=NaN +scale=3.0E-4 +unit=V diff --git a/devices/led_ctrl_1.properties b/devices/led_ctrl_1.properties new file mode 100644 index 0000000..8360687 --- /dev/null +++ b/devices/led_ctrl_1.properties @@ -0,0 +1,9 @@ +#Mon Dec 03 22:45:14 CET 2018 +maxValue=0.4 +minValue=0.0 +offset=0.0 +precision=2 +resolution=NaN +scale=3.0E-4 +sign_bit=0 +unit=V diff --git a/devices/led_ctrl_2.properties b/devices/led_ctrl_2.properties new file mode 100644 index 0000000..8360687 --- /dev/null +++ b/devices/led_ctrl_2.properties @@ -0,0 +1,9 @@ +#Mon Dec 03 22:45:14 CET 2018 +maxValue=0.4 +minValue=0.0 +offset=0.0 +precision=2 +resolution=NaN +scale=3.0E-4 +sign_bit=0 +unit=V diff --git a/devices/led_ctrl_3.properties b/devices/led_ctrl_3.properties new file mode 100644 index 0000000..8360687 --- /dev/null +++ b/devices/led_ctrl_3.properties @@ -0,0 +1,9 @@ +#Mon Dec 03 22:45:14 CET 2018 +maxValue=0.4 +minValue=0.0 +offset=0.0 +precision=2 +resolution=NaN +scale=3.0E-4 +sign_bit=0 +unit=V diff --git a/devices/led_level.properties b/devices/led_level.properties new file mode 100644 index 0000000..52dee03 --- /dev/null +++ b/devices/led_level.properties @@ -0,0 +1,9 @@ +#Tue Jun 19 16:41:24 CEST 2018 +maxValue=NaN +minValue=NaN +offset=0.0 +precision=-1 +resolution=NaN +scale=1.0 +sign_bit=0 +unit=null diff --git a/devices/m1.properties b/devices/m1.properties new file mode 100644 index 0000000..1cf4553 --- /dev/null +++ b/devices/m1.properties @@ -0,0 +1,13 @@ +#Fri Jun 30 09:37:38 CEST 2017 +defaultSpeed=1.0 +estbilizationDelay=0 +maxSpeed=10.0 +maxValue=10.0 +minSpeed=0.1 +minValue=-10.0 +offset=0.0 +precision=2 +resolution=NaN +rotation=false +scale=1.0 +unit=mm diff --git a/devices/m2.properties b/devices/m2.properties new file mode 100644 index 0000000..1cf4553 --- /dev/null +++ b/devices/m2.properties @@ -0,0 +1,13 @@ +#Fri Jun 30 09:37:38 CEST 2017 +defaultSpeed=1.0 +estbilizationDelay=0 +maxSpeed=10.0 +maxValue=10.0 +minSpeed=0.1 +minValue=-10.0 +offset=0.0 +precision=2 +resolution=NaN +rotation=false +scale=1.0 +unit=mm diff --git a/devices/monitoring_cam.properties b/devices/monitoring_cam.properties new file mode 100644 index 0000000..fa56b35 --- /dev/null +++ b/devices/monitoring_cam.properties @@ -0,0 +1,20 @@ +#Thu Aug 09 11:01:09 CEST 2018 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/n2_pressure.properties b/devices/n2_pressure.properties new file mode 100644 index 0000000..e476b09 --- /dev/null +++ b/devices/n2_pressure.properties @@ -0,0 +1,5 @@ +#Thu Mar 01 11:13:34 CET 2018 +offset=0.0 +precision=-1 +scale=1.0 +unit=null diff --git a/devices/p1.properties b/devices/p1.properties new file mode 100644 index 0000000..07d9ba5 --- /dev/null +++ b/devices/p1.properties @@ -0,0 +1,9 @@ +#Fri Jun 30 09:37:38 CEST 2017 +maxValue=1000.0 +minValue=0.0 +offset=0.0 +precision=-1 +resolution=NaN +rotation=false +scale=1.0 +unit=mm diff --git a/devices/phase_separator.properties b/devices/phase_separator.properties new file mode 100644 index 0000000..122f8e9 --- /dev/null +++ b/devices/phase_separator.properties @@ -0,0 +1,8 @@ +#Wed Feb 28 17:35:59 CET 2018 +maxValue=30000.0 +minValue=0.0 +offset=0.0 +precision=-1 +resolution=NaN +scale=0.1 +unit=% diff --git a/devices/phase_separator_level.properties b/devices/phase_separator_level.properties new file mode 100644 index 0000000..92a5279 --- /dev/null +++ b/devices/phase_separator_level.properties @@ -0,0 +1,6 @@ +#Tue Jun 19 16:41:20 CEST 2018 +offset=-25.81632 +precision=2 +scale=0.003888 +sign_bit=0 +unit=% diff --git a/devices/rim_heater_temp.properties b/devices/rim_heater_temp.properties new file mode 100644 index 0000000..e1c3b95 --- /dev/null +++ b/devices/rim_heater_temp.properties @@ -0,0 +1,6 @@ +#Tue Jun 19 16:41:20 CEST 2018 +offset=-25.81632 +precision=2 +scale=0.003888 +sign_bit=0 +unit=C diff --git a/devices/robot x.properties b/devices/robot x.properties new file mode 100644 index 0000000..02ffbf3 --- /dev/null +++ b/devices/robot x.properties @@ -0,0 +1,9 @@ +#Tue Sep 12 15:00:38 CEST 2017 +maxValue=NaN +minValue=NaN +offset=0.0 +precision=-1 +resolution=NaN +rotation=false +scale=1.0 +unit=null diff --git a/devices/robot.properties b/devices/robot.properties new file mode 100644 index 0000000..97f6ad6 --- /dev/null +++ b/devices/robot.properties @@ -0,0 +1,8 @@ +#Thu Jul 21 08:35:47 CEST 2016 +offsetReadAnalogInput=0 +offsetReadAnalogOutput=0 +offsetReadDigitalInput=0 +offsetReadDigitalOutput=0 +offsetWriteAnalogOutput=0 +offsetWriteDigitalOutput=0 +timeout=1000 diff --git a/devices/robot_j1.properties b/devices/robot_j1.properties new file mode 100644 index 0000000..bc3a381 --- /dev/null +++ b/devices/robot_j1.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=180.0 +minValue=-180.0 +offset=0.0 +precision=2 +resolution=0.1 +rotation=false +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_j2.properties b/devices/robot_j2.properties new file mode 100644 index 0000000..6a892bc --- /dev/null +++ b/devices/robot_j2.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=127.5 +minValue=-127.5 +offset=0.0 +precision=2 +resolution=0.1 +rotation=false +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_j3.properties b/devices/robot_j3.properties new file mode 100644 index 0000000..07bff75 --- /dev/null +++ b/devices/robot_j3.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=152.5 +minValue=-152.5 +offset=0.0 +precision=2 +resolution=0.1 +rotation=false +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_j4.properties b/devices/robot_j4.properties new file mode 100644 index 0000000..41d8586 --- /dev/null +++ b/devices/robot_j4.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=270.0 +minValue=-270.0 +offset=0.0 +precision=2 +resolution=0.1 +rotation=false +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_j5.properties b/devices/robot_j5.properties new file mode 100644 index 0000000..dab429f --- /dev/null +++ b/devices/robot_j5.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=132.5 +minValue=-122.5 +offset=0.0 +precision=2 +resolution=0.1 +rotation=false +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_j6.properties b/devices/robot_j6.properties new file mode 100644 index 0000000..d688634 --- /dev/null +++ b/devices/robot_j6.properties @@ -0,0 +1,10 @@ +#Fri Aug 24 14:56:42 CEST 2018 +maxValue=400.0 +minValue=-400.0 +offset=0.0 +precision=2 +resolution=0.1 +rotation=false +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_modbus.properties b/devices/robot_modbus.properties new file mode 100644 index 0000000..31a13be --- /dev/null +++ b/devices/robot_modbus.properties @@ -0,0 +1,8 @@ +#Thu Jul 21 12:02:04 CEST 2016 +offsetReadAnalogInput=0 +offsetReadAnalogOutput=0 +offsetReadDigitalInput=0 +offsetReadDigitalOutput=0 +offsetWriteAnalogOutput=0 +offsetWriteDigitalOutput=0 +timeout=1000 diff --git a/devices/robot_rx.properties b/devices/robot_rx.properties new file mode 100644 index 0000000..df63f03 --- /dev/null +++ b/devices/robot_rx.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=180.0 +minValue=-180.0 +offset=0.0 +precision=2 +resolution=0.05 +rotation=true +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_ry.properties b/devices/robot_ry.properties new file mode 100644 index 0000000..a789ebf --- /dev/null +++ b/devices/robot_ry.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=180.0 +minValue=-180.0 +offset=0.0 +precision=-2 +resolution=0.05 +rotation=true +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_rz.properties b/devices/robot_rz.properties new file mode 100644 index 0000000..2b88035 --- /dev/null +++ b/devices/robot_rz.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=360.0 +minValue=-360.0 +offset=0.0 +precision=2 +resolution=0.1 +rotation=true +scale=1.0 +sign_bit=0 +unit=deg diff --git a/devices/robot_x.properties b/devices/robot_x.properties new file mode 100644 index 0000000..5cdadcc --- /dev/null +++ b/devices/robot_x.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=1000.0 +minValue=-1000.0 +offset=0.0 +precision=2 +resolution=0.05 +rotation=false +scale=1.0 +sign_bit=0 +unit=mm diff --git a/devices/robot_y.properties b/devices/robot_y.properties new file mode 100644 index 0000000..eb8022e --- /dev/null +++ b/devices/robot_y.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=1000.0 +minValue=-1000.0 +offset=0.0 +precision=2 +resolution=0.05 +rotation=false +scale=1.0 +sign_bit=0 +unit=null diff --git a/devices/robot_z.properties b/devices/robot_z.properties new file mode 100644 index 0000000..eb8022e --- /dev/null +++ b/devices/robot_z.properties @@ -0,0 +1,10 @@ +#Tue Jun 19 16:41:28 CEST 2018 +maxValue=1000.0 +minValue=-1000.0 +offset=0.0 +precision=2 +resolution=0.05 +rotation=false +scale=1.0 +sign_bit=0 +unit=null diff --git a/devices/ry.properties b/devices/ry.properties new file mode 100644 index 0000000..f43c3d2 --- /dev/null +++ b/devices/ry.properties @@ -0,0 +1,17 @@ +#Fri Aug 10 15:47:14 CEST 2018 +defaultSpeed=50.0 +estbilizationDelay=0 +hasEnable=false +homingType=None +maxSpeed=NaN +maxValue=0.0 +minSpeed=NaN +minValue=0.0 +offset=0.0 +precision=3 +resolution=0.001 +rotation=false +scale=1.0 +sign_bit=0 +startRetries=1 +unit=deg diff --git a/devices/smart_magnet.properties b/devices/smart_magnet.properties new file mode 100644 index 0000000..012c86e --- /dev/null +++ b/devices/smart_magnet.properties @@ -0,0 +1,8 @@ +#Thu Oct 25 16:47:21 CEST 2018 +holdingCurrent=30.0 +mountCurrent=10.0 +remanenceCurrent=-10.0 +restingCurrent=10.0 +reverseCurrent=-10.0 +reverseTime=0.4 +unmountCurrent=10.0 diff --git a/devices/smc_current.properties b/devices/smc_current.properties new file mode 100644 index 0000000..aa71f58 --- /dev/null +++ b/devices/smc_current.properties @@ -0,0 +1,9 @@ +#Tue Jun 19 16:41:20 CEST 2018 +maxValue=50.0 +minValue=-50.0 +offset=0.0 +precision=2 +resolution=NaN +scale=0.003 +sign_bit=0 +unit=mA diff --git a/devices/smc_current_rb.properties b/devices/smc_current_rb.properties new file mode 100644 index 0000000..7709ada --- /dev/null +++ b/devices/smc_current_rb.properties @@ -0,0 +1,6 @@ +#Tue Jun 19 16:45:06 CEST 2018 +offset=0.0 +precision=2 +scale=0.003 +sign_bit=15 +unit=mA diff --git a/devices/src1.properties b/devices/src1.properties new file mode 100644 index 0000000..a0b5d6d --- /dev/null +++ b/devices/src1.properties @@ -0,0 +1,24 @@ +#Thu Sep 22 14:45:06 CEST 2016 +colormap=Temperature +colormapAutomatic=true +colormapMax=255.0 +colormapMin=0.0 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/src2.properties b/devices/src2.properties new file mode 100644 index 0000000..2bf8406 --- /dev/null +++ b/devices/src2.properties @@ -0,0 +1,24 @@ +#Thu Sep 22 14:45:06 CEST 2016 +colormap=Grayscale +colormapAutomatic=true +colormapMax=255.0 +colormapMin=0.0 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/top_cam.properties b/devices/top_cam.properties new file mode 100644 index 0000000..827552b --- /dev/null +++ b/devices/top_cam.properties @@ -0,0 +1,20 @@ +#Thu Aug 09 11:46:12 CEST 2018 +flipHorizontally=false +flipVertically=false +grayscale=false +invert=false +rescaleFactor=1.0 +rescaleOffset=0.0 +roiHeight=-1 +roiWidth=-1 +roiX=0 +roiY=0 +rotation=0.0 +rotationCrop=false +scale=1.0 +spatialCalOffsetX=NaN +spatialCalOffsetY=NaN +spatialCalScaleX=NaN +spatialCalScaleY=NaN +spatialCalUnits=mm +transpose=false diff --git a/devices/ue.properties b/devices/ue.properties new file mode 100644 index 0000000..f241f62 --- /dev/null +++ b/devices/ue.properties @@ -0,0 +1,6 @@ +#Thu Aug 31 16:41:09 CEST 2017 +baudRate=9600 +dataBits=DB_8 +parity=None +port=null +stopBits=SB_1 diff --git a/devices/wago.properties b/devices/wago.properties new file mode 100644 index 0000000..f2650ea --- /dev/null +++ b/devices/wago.properties @@ -0,0 +1,8 @@ +#Wed Feb 28 16:27:51 CET 2018 +offsetReadAnalogInput=0 +offsetReadAnalogOutput=0x200 +offsetReadDigitalInput=0 +offsetReadDigitalOutput=0x200 +offsetWriteAnalogOutput=0 +offsetWriteDigitalOutput=0 +timeout=1000 diff --git a/plugins/BarcodeReaderPanel.form b/plugins/BarcodeReaderPanel.form new file mode 100644 index 0000000..3e615f6 --- /dev/null +++ b/plugins/BarcodeReaderPanel.form @@ -0,0 +1,118 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/BarcodeReaderPanel.java b/plugins/BarcodeReaderPanel.java new file mode 100644 index 0000000..cb269c2 --- /dev/null +++ b/plugins/BarcodeReaderPanel.java @@ -0,0 +1,162 @@ +import ch.psi.pshell.core.Context; +import ch.psi.pshell.swing.DevicePanel; +import ch.psi.utils.swing.SwingUtils; +import java.util.concurrent.CompletableFuture; + +/** + * + */ +public class BarcodeReaderPanel extends DevicePanel { + + volatile boolean enabled; + public BarcodeReaderPanel() { + initComponents(); + this.startTimer(100); + } + + + CompletableFuture future; + + @Override + public void onTimer(){ + if ((getDevice()!=null) && enabled){ + if ((future==null) || (future.isDone())){ + future = Context.getInstance().evalLineBackgroundAsync("barcode_reader.get()"); + } + } + } + + + void execute(String statement, boolean showReturn){ + try { + Context.getInstance().evalLineBackgroundAsync(statement).handle((ret, ex) -> { + if (BarcodeReaderPanel.this.isShowing()){ + if (ex != null){ + showException((Exception)ex); + } else if (showReturn){ + if (ret == null){ + SwingUtils.showMessage(this, "Return", "No code detected", 20000); + } else { + SwingUtils.showMessage(this, "Return", "Detected code: " +ret, 20000); + } + } + } + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel3 = new javax.swing.JPanel(); + buttonEnable = new javax.swing.JButton(); + buttonDisable = new javax.swing.JButton(); + buttonRead = new javax.swing.JButton(); + deviceStatePanel1 = new ch.psi.pshell.swing.DeviceStatePanel(); + deviceValuePanel1 = new ch.psi.pshell.swing.DeviceValuePanel(); + + jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Commands")); + + buttonEnable.setText("Enable"); + buttonEnable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonEnableActionPerformed(evt); + } + }); + + buttonDisable.setText("Disable"); + buttonDisable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonDisableActionPerformed(evt); + } + }); + + buttonRead.setText("Read"); + buttonRead.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonReadActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addComponent(buttonEnable) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonDisable) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonRead) + .addContainerGap()) + ); + + jPanel3Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonDisable, buttonEnable, buttonRead}); + + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonEnable) + .addComponent(buttonDisable) + .addComponent(buttonRead)) + .addContainerGap()) + ); + + deviceStatePanel1.setDeviceName("barcode_reader"); + + deviceValuePanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Value")); + deviceValuePanel1.setDeviceName("barcode_reader"); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(deviceValuePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(deviceStatePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(deviceValuePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(deviceStatePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0)) + ); + }// //GEN-END:initComponents + + private void buttonEnableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEnableActionPerformed + execute("barcode_reader.enable()", false); + enabled = true; + }//GEN-LAST:event_buttonEnableActionPerformed + + private void buttonDisableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDisableActionPerformed + enabled = false; + execute("barcode_reader.disable()", false); + }//GEN-LAST:event_buttonDisableActionPerformed + + private void buttonReadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonReadActionPerformed + enabled = false; + execute("barcode_reader.read(5.0) ", true); + }//GEN-LAST:event_buttonReadActionPerformed + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton buttonDisable; + private javax.swing.JButton buttonEnable; + private javax.swing.JButton buttonRead; + private ch.psi.pshell.swing.DeviceStatePanel deviceStatePanel1; + private ch.psi.pshell.swing.DeviceValuePanel deviceValuePanel1; + private javax.swing.JPanel jPanel3; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/Beeper.java b/plugins/Beeper.java new file mode 100644 index 0000000..c1fea67 --- /dev/null +++ b/plugins/Beeper.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.device.*; +import com.sun.jna.Function; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import com.sun.jna.ptr.IntByReference; +import com.sun.jna.win32.StdCallLibrary; +import com.sun.jna.win32.W32APIFunctionMapper; +import com.sun.jna.win32.W32APITypeMapper; +import java.util.HashMap; +import java.util.Map; + +/** + */ +public class Beeper extends DeviceBase { + + public Beeper(String name) { + super(name); + } + + // JNA Mapping + static Map UNICODE_OPTIONS = new HashMap() { + + { + put("type-mapper", W32APITypeMapper.UNICODE); + put("function-mapper", W32APIFunctionMapper.UNICODE); + } + }; + + interface Kernel32 extends StdCallLibrary { + + public static final String LIBRARY_NAME = "kernel32"; + Kernel32 INSTANCE = (Kernel32) Native.loadLibrary(LIBRARY_NAME, Kernel32.class, UNICODE_OPTIONS); + Kernel32 SYNC_INSTANCE = (Kernel32) Native.synchronizedLibrary(INSTANCE); + + boolean Beep(int FREQUENCY, int DURATION); + + void Sleep(int DURATION); + + int CreateEventW(Pointer securityAttributes, boolean manualReset, boolean initialState, String name); + + int CreateThread(/*Pointer*/int lpThreadAttributes, IntByReference dwStackSize, Function lpStartAddress, Structure lpParameter, int dwCreationFlags, IntByReference lpThreadId); + public static final int STILL_ACTIVE = 259; + + int GetExitCodeThread(int hThread, IntByReference lpExitCode); + + int GetLastError(); + + boolean CloseHandle(int handle); + + } + private final int mEventHandle = Kernel32.INSTANCE.CreateEventW(Pointer.NULL, true, false, null); + + + //Public interface + public int getLastError(){ + return Kernel32.SYNC_INSTANCE.GetLastError(); + } + + public void sleep(int duration){ + Kernel32.SYNC_INSTANCE.Sleep(duration); + } + + public void beep(int frequency, int duration){ + Kernel32.SYNC_INSTANCE.Beep(frequency, duration); + } + +} diff --git a/plugins/Commands.form b/plugins/Commands.form new file mode 100644 index 0000000..70c71b4 --- /dev/null +++ b/plugins/Commands.form @@ -0,0 +1,803 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/Commands.java b/plugins/Commands.java new file mode 100644 index 0000000..f861b06 --- /dev/null +++ b/plugins/Commands.java @@ -0,0 +1,914 @@ +/* + * Copyright (c) 2014-2017 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.device.Device; +import ch.psi.pshell.device.DeviceAdapter; +import ch.psi.pshell.device.GenericDevice; +import ch.psi.pshell.ui.Panel; +import ch.psi.utils.State; +import ch.psi.utils.swing.SwingUtils; +import java.awt.Component; +import javax.swing.JComponent; +import javax.swing.JSpinner; +import javax.swing.JTextField; + +/** + * + */ +public class Commands extends Panel { + + public Commands() { + initComponents(); + ((JSpinner.DefaultEditor)spinnerSegment.getEditor()).getTextField().setHorizontalAlignment(JTextField.CENTER); + ((JSpinner.DefaultEditor)spinnerPuck.getEditor()).getTextField().setHorizontalAlignment(JTextField.CENTER); + ((JSpinner.DefaultEditor)spinnerSample.getEditor()).getTextField().setHorizontalAlignment(JTextField.CENTER); + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + GenericDevice basePlate = getDevice("BasePlate"); + if (basePlate != null){ + basePlate.addListener(new DeviceAdapter() { + @Override + public void onValueChanged(Device device, Object value, Object former) { + if (value!=null){ + String segment = ((Object[])value)[0].toString(); + spinnerSegment.setValue(segment); + Integer puck = (Integer) ((Object[])value)[1]; + spinnerPuck.setValue(Integer.valueOf(puck)); + Integer sample = (Integer) ((Object[])value)[2]; + if (sample!=null){ + spinnerSample.setValue(Integer.valueOf(sample)); + } + } + } + }); + } + } + + @Override + public void onStateChange(State state, State former) { + boolean enabled = (state == State.Ready); + for (Component c: SwingUtils.getComponentsByType(this, JComponent.class)){ + c.setEnabled(enabled); + } + spinnerSegment.setEnabled(enabled && !checkAuxiliary.isSelected()); + spinnerPuck.setEnabled(enabled && !checkAuxiliary.isSelected()); + buttonScanPuck.setEnabled(enabled && !checkAuxiliary.isSelected()); + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + //Callback to perform update - in event thread + @Override + protected void doUpdate() { + } + + @Override + public boolean isActive() { + return true; + } + + + void execute(String statement){ + execute(statement, false); + } + + void execute(String statement, boolean background){ + execute(statement, background, false); + } + + void execute(String statement, boolean background, boolean showReturn){ + try { + evalAsync(statement, background).handle((ret, ex) -> { + if (ex != null){ + showException((Exception)ex); + } else if (showReturn){ + SwingUtils.showMessage(getTopLevel(), "Return", String.valueOf(ret)); + } + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + } + + void execute(String script, Object args){ + try { + runAsync(script, args).handle((ret, ex) -> { + if (ex != null){ + showException((Exception)ex); + } + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + } + + + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jTabbedPane1 = new javax.swing.JTabbedPane(); + tabCommands = new javax.swing.JPanel(); + pnDry = new javax.swing.JPanel(); + jLabel6 = new javax.swing.JLabel(); + spinnerDryTime = new ch.psi.utils.swing.HorizontalSpinner(); + buttonDry = new javax.swing.JButton(); + spinnerDrySpeed = new ch.psi.utils.swing.HorizontalSpinner(); + jLabel7 = new javax.swing.JLabel(); + ckeckParkOnDry = new javax.swing.JCheckBox(); + pnTransfer = new javax.swing.JPanel(); + buttonMount = new javax.swing.JButton(); + jPanel5 = new javax.swing.JPanel(); + jLabel4 = new javax.swing.JLabel(); + checkForce = new javax.swing.JCheckBox(); + spinnerSample = new ch.psi.utils.swing.HorizontalSpinner(); + spinnerPuck = new ch.psi.utils.swing.HorizontalSpinner(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + spinnerSegment = new ch.psi.utils.swing.HorizontalSpinner(); + jLabel3 = new javax.swing.JLabel(); + jLabel5 = new javax.swing.JLabel(); + checkDatamatrix = new javax.swing.JCheckBox(); + buttonUnmount = new javax.swing.JButton(); + buttonScanPin = new javax.swing.JButton(); + buttonScanPuck = new javax.swing.JButton(); + checkAuxiliary = new javax.swing.JCheckBox(); + jPanel1 = new javax.swing.JPanel(); + buttonGripperScan = new javax.swing.JButton(); + buttonTrash = new javax.swing.JButton(); + tabAdvanced = new javax.swing.JPanel(); + pnLowLevel = new javax.swing.JPanel(); + buttonMovePark = new javax.swing.JButton(); + buttonMoveCold = new javax.swing.JButton(); + buttonMoveGonio = new javax.swing.JButton(); + buttonMoveHeater = new javax.swing.JButton(); + buttonGetGonio = new javax.swing.JButton(); + buttonPutGonio = new javax.swing.JButton(); + buttonMoveDewar = new javax.swing.JButton(); + buttonMoveHome = new javax.swing.JButton(); + buttonMoveScanner = new javax.swing.JButton(); + buttonGetDewar = new javax.swing.JButton(); + buttonPutDewar = new javax.swing.JButton(); + buttonMoveAux = new javax.swing.JButton(); + buttonGetAux = new javax.swing.JButton(); + buttonPutAux = new javax.swing.JButton(); + pnDatabase = new javax.swing.JPanel(); + buttonClearSampleDb = new javax.swing.JButton(); + buttonResetPuckIds = new javax.swing.JButton(); + pnMotion = new javax.swing.JPanel(); + buttonRecover = new javax.swing.JButton(); + buttonEnableAll = new javax.swing.JButton(); + + pnDry.setBorder(javax.swing.BorderFactory.createTitledBorder("Drying")); + + jLabel6.setText("Heat time(s):"); + + spinnerDryTime.setModel(new javax.swing.SpinnerNumberModel(30.0d, 1.0d, 30.0d, 1.0d)); + + buttonDry.setText("Dry"); + buttonDry.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonDryActionPerformed(evt); + } + }); + + spinnerDrySpeed.setModel(new javax.swing.SpinnerNumberModel(0.5d, 0.1d, 10.0d, 1.0d)); + + jLabel7.setText("Speed(%):"); + + ckeckParkOnDry.setText("Park on finish"); + + javax.swing.GroupLayout pnDryLayout = new javax.swing.GroupLayout(pnDry); + pnDry.setLayout(pnDryLayout); + pnDryLayout.setHorizontalGroup( + pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDryLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonDry, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(ckeckParkOnDry)) + .addGap(18, 25, Short.MAX_VALUE) + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(jLabel6) + .addComponent(jLabel7)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(spinnerDrySpeed, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(spinnerDryTime, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + pnDryLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonDry, spinnerDrySpeed, spinnerDryTime}); + + pnDryLayout.setVerticalGroup( + pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDryLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDryLayout.createSequentialGroup() + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonDry) + .addComponent(spinnerDryTime, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnDryLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(spinnerDrySpeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel7) + .addComponent(ckeckParkOnDry))) + .addComponent(jLabel6)) + .addContainerGap()) + ); + + pnTransfer.setBorder(javax.swing.BorderFactory.createTitledBorder("Sample Transfer")); + + buttonMount.setText("Mount"); + buttonMount.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMountActionPerformed(evt); + } + }); + + jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel4.setText("Force:"); + + checkForce.setSelected(true); + checkForce.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + + spinnerSample.setModel(new javax.swing.SpinnerNumberModel(1, 1, 16, 1)); + + spinnerPuck.setModel(new javax.swing.SpinnerNumberModel(1, 1, 5, 1)); + + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel1.setText("Segment:"); + + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel2.setText("Puck:"); + + spinnerSegment.setModel(new javax.swing.SpinnerListModel(new String[] {"A", "B", "C", "D", "E", "F"})); + + jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel3.setText("Sample:"); + + jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel5.setText("Read DM:"); + + checkDatamatrix.setHorizontalTextPosition(javax.swing.SwingConstants.LEADING); + + javax.swing.GroupLayout jPanel5Layout = new javax.swing.GroupLayout(jPanel5); + jPanel5.setLayout(jPanel5Layout); + jPanel5Layout.setHorizontalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel3) + .addComponent(jLabel2) + .addComponent(jLabel1) + .addComponent(jLabel4) + .addComponent(jLabel5)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(spinnerPuck, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(checkForce) + .addComponent(checkDatamatrix) + .addComponent(spinnerSample, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(spinnerSegment, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(0, 0, 0)) + ); + + jPanel5Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel1, jLabel2, jLabel3, jLabel4, jLabel5}); + + jPanel5Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {spinnerPuck, spinnerSample, spinnerSegment}); + + jPanel5Layout.setVerticalGroup( + jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel5Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel1) + .addComponent(spinnerSegment, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel2) + .addComponent(spinnerPuck, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel3) + .addComponent(spinnerSample, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel4) + .addComponent(checkForce)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel5Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel5) + .addComponent(checkDatamatrix))) + ); + + buttonUnmount.setText("Unmount"); + buttonUnmount.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonUnmountActionPerformed(evt); + } + }); + + buttonScanPin.setText("Scan Pin"); + buttonScanPin.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonScanPinActionPerformed(evt); + } + }); + + buttonScanPuck.setText("Scan Puck"); + buttonScanPuck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonScanPuckActionPerformed(evt); + } + }); + + checkAuxiliary.setText("Auxiliary"); + checkAuxiliary.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + checkAuxiliaryActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnTransferLayout = new javax.swing.GroupLayout(pnTransfer); + pnTransfer.setLayout(pnTransferLayout); + pnTransferLayout.setHorizontalGroup( + pnTransferLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnTransferLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnTransferLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonMount, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonUnmount, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonScanPin, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonScanPuck, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(checkAuxiliary)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + pnTransferLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonMount, buttonScanPin, buttonUnmount}); + + pnTransferLayout.setVerticalGroup( + pnTransferLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnTransferLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnTransferLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGroup(pnTransferLayout.createSequentialGroup() + .addComponent(buttonMount) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonUnmount) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonScanPin) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonScanPuck) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(checkAuxiliary))) + .addContainerGap()) + ); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Gripper")); + + buttonGripperScan.setText("Scan"); + buttonGripperScan.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonGripperScanActionPerformed(evt); + } + }); + + buttonTrash.setText("Trash"); + buttonTrash.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonTrashActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(buttonGripperScan, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonTrash, javax.swing.GroupLayout.PREFERRED_SIZE, 100, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonGripperScan) + .addComponent(buttonTrash)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout tabCommandsLayout = new javax.swing.GroupLayout(tabCommands); + tabCommands.setLayout(tabCommandsLayout); + tabCommandsLayout.setHorizontalGroup( + tabCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tabCommandsLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(tabCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pnDry, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnTransfer, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))) + ); + tabCommandsLayout.setVerticalGroup( + tabCommandsLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tabCommandsLayout.createSequentialGroup() + .addContainerGap() + .addComponent(pnDry, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnTransfer, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + jTabbedPane1.addTab("Commands", tabCommands); + + pnLowLevel.setBorder(javax.swing.BorderFactory.createTitledBorder("Low-level Motion Commands")); + + buttonMovePark.setText("Move Park"); + buttonMovePark.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveParkActionPerformed(evt); + } + }); + + buttonMoveCold.setText("Move Cold"); + buttonMoveCold.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveColdActionPerformed(evt); + } + }); + + buttonMoveGonio.setText("Move Gonio"); + buttonMoveGonio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveGonioActionPerformed(evt); + } + }); + + buttonMoveHeater.setText("Move Heater"); + buttonMoveHeater.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveHeaterActionPerformed(evt); + } + }); + + buttonGetGonio.setText("Get Gonio"); + buttonGetGonio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonGetGonioActionPerformed(evt); + } + }); + + buttonPutGonio.setText("Put Gonio"); + buttonPutGonio.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPutGonioActionPerformed(evt); + } + }); + + buttonMoveDewar.setText("Move Dewar"); + buttonMoveDewar.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveDewarActionPerformed(evt); + } + }); + + buttonMoveHome.setText("Move Home"); + buttonMoveHome.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveHomeActionPerformed(evt); + } + }); + + buttonMoveScanner.setText("Move Scanner"); + buttonMoveScanner.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveScannerActionPerformed(evt); + } + }); + + buttonGetDewar.setText("Get Dewar"); + buttonGetDewar.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonGetDewarActionPerformed(evt); + } + }); + + buttonPutDewar.setText("Put Dewar"); + buttonPutDewar.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPutDewarActionPerformed(evt); + } + }); + + buttonMoveAux.setText("Move Aux"); + buttonMoveAux.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonMoveAuxActionPerformed(evt); + } + }); + + buttonGetAux.setText("Get Aux"); + buttonGetAux.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonGetAuxActionPerformed(evt); + } + }); + + buttonPutAux.setText("Put Aux"); + buttonPutAux.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPutAuxActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnLowLevelLayout = new javax.swing.GroupLayout(pnLowLevel); + pnLowLevel.setLayout(pnLowLevelLayout); + pnLowLevelLayout.setHorizontalGroup( + pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnLowLevelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonMovePark, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveAux) + .addComponent(buttonMoveCold, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveHeater) + .addComponent(buttonGetGonio) + .addComponent(buttonGetDewar, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonGetAux, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 64, Short.MAX_VALUE) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(buttonPutDewar, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonPutGonio, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveGonio, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveHome, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveDewar, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonMoveScanner) + .addComponent(buttonPutAux, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + pnLowLevelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonGetAux, buttonGetDewar, buttonGetGonio, buttonMoveAux, buttonMoveCold, buttonMoveDewar, buttonMoveGonio, buttonMoveHeater, buttonMoveHome, buttonMovePark, buttonMoveScanner, buttonPutAux, buttonPutDewar, buttonPutGonio}); + + pnLowLevelLayout.setVerticalGroup( + pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnLowLevelLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonGetDewar) + .addComponent(buttonPutDewar)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonGetAux) + .addComponent(buttonPutAux)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonGetGonio) + .addComponent(buttonPutGonio)) + .addGap(18, 18, 18) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveGonio) + .addComponent(buttonMoveAux)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMovePark) + .addComponent(buttonMoveHome)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveDewar) + .addComponent(buttonMoveCold)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(pnLowLevelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonMoveHeater) + .addComponent(buttonMoveScanner)) + .addContainerGap()) + ); + + pnDatabase.setBorder(javax.swing.BorderFactory.createTitledBorder("Database")); + + buttonClearSampleDb.setText("Clear Sample Db"); + buttonClearSampleDb.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonClearSampleDbActionPerformed(evt); + } + }); + + buttonResetPuckIds.setText("Reset Puck IDs"); + buttonResetPuckIds.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonResetPuckIdsActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnDatabaseLayout = new javax.swing.GroupLayout(pnDatabase); + pnDatabase.setLayout(pnDatabaseLayout); + pnDatabaseLayout.setHorizontalGroup( + pnDatabaseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseLayout.createSequentialGroup() + .addContainerGap() + .addComponent(buttonClearSampleDb) + .addGap(18, 18, Short.MAX_VALUE) + .addComponent(buttonResetPuckIds) + .addContainerGap()) + ); + + pnDatabaseLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonClearSampleDb, buttonResetPuckIds}); + + pnDatabaseLayout.setVerticalGroup( + pnDatabaseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnDatabaseLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnDatabaseLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonClearSampleDb) + .addComponent(buttonResetPuckIds)) + .addContainerGap()) + ); + + pnMotion.setBorder(javax.swing.BorderFactory.createTitledBorder("Motion")); + + buttonRecover.setText("Dewar Recovery"); + buttonRecover.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonRecoverActionPerformed(evt); + } + }); + + buttonEnableAll.setText("Enable Motion"); + buttonEnableAll.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonEnableAllActionPerformed(evt); + } + }); + + javax.swing.GroupLayout pnMotionLayout = new javax.swing.GroupLayout(pnMotion); + pnMotion.setLayout(pnMotionLayout); + pnMotionLayout.setHorizontalGroup( + pnMotionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnMotionLayout.createSequentialGroup() + .addContainerGap() + .addComponent(buttonRecover) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonEnableAll) + .addContainerGap()) + ); + + pnMotionLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonEnableAll, buttonRecover}); + + pnMotionLayout.setVerticalGroup( + pnMotionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(pnMotionLayout.createSequentialGroup() + .addContainerGap() + .addGroup(pnMotionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonRecover) + .addComponent(buttonEnableAll)) + .addContainerGap()) + ); + + javax.swing.GroupLayout tabAdvancedLayout = new javax.swing.GroupLayout(tabAdvanced); + tabAdvanced.setLayout(tabAdvancedLayout); + tabAdvancedLayout.setHorizontalGroup( + tabAdvancedLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tabAdvancedLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(tabAdvancedLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(pnMotion, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnDatabase, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(pnLowLevel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, 0)) + ); + tabAdvancedLayout.setVerticalGroup( + tabAdvancedLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(tabAdvancedLayout.createSequentialGroup() + .addContainerGap() + .addComponent(pnLowLevel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnDatabase, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(pnMotion, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + jTabbedPane1.addTab("Advanced", tabAdvanced); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane1, javax.swing.GroupLayout.Alignment.TRAILING) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + ); + }// //GEN-END:initComponents + + private void buttonEnableAllActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEnableAllActionPerformed + execute("enable_motion()", true); + }//GEN-LAST:event_buttonEnableAllActionPerformed + + private void buttonMountActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMountActionPerformed + String segment = checkAuxiliary.isSelected() ? "X" : (String) spinnerSegment.getValue(); + int puck = checkAuxiliary.isSelected() ? 1 :(Integer) spinnerPuck.getValue(); + int sample = (Integer) spinnerSample.getValue(); + String force = checkForce.isSelected() ? "True" : "False"; + String readDatamatrix = checkDatamatrix.isSelected() ? "True" : "False"; + execute("mount('" + segment + "'," + puck + "," + sample + ", force=" + force + ", read_dm=" + readDatamatrix + ")"); + + }//GEN-LAST:event_buttonMountActionPerformed + + private void buttonMoveAuxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveAuxActionPerformed + execute("move_aux()"); + }//GEN-LAST:event_buttonMoveAuxActionPerformed + + private void buttonUnmountActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonUnmountActionPerformed + String segment = checkAuxiliary.isSelected() ? "X" : (String) spinnerSegment.getValue(); + int puck = checkAuxiliary.isSelected() ? 1 :(Integer) spinnerPuck.getValue(); + int sample = (Integer) spinnerSample.getValue(); + String force = checkForce.isSelected() ? "True" : "False"; + execute("unmount('" + segment + "'," + puck + "," + sample + ", force=" + force + ")"); + }//GEN-LAST:event_buttonUnmountActionPerformed + + private void buttonGetDewarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGetDewarActionPerformed + String segment = (String) spinnerSegment.getValue(); + int puck = (Integer) spinnerPuck.getValue(); + int sample = (Integer) spinnerSample.getValue(); + String force = checkForce.isSelected() ? "True" : "False"; + execute("get_dewar('" + segment + "'," + puck + "," + sample + ", force=" + force + ")"); + }//GEN-LAST:event_buttonGetDewarActionPerformed + + private void buttonPutDewarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPutDewarActionPerformed + String segment = (String) spinnerSegment.getValue(); + int puck = (Integer) spinnerPuck.getValue(); + int sample = (Integer) spinnerSample.getValue(); + String force = checkForce.isSelected() ? "True" : "False"; + execute("put_dewar('" + segment + "'," + puck + "," + sample + ", force=" + force + ")"); + }//GEN-LAST:event_buttonPutDewarActionPerformed + + private void buttonGetGonioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGetGonioActionPerformed + String force = checkForce.isSelected() ? "True" : "False"; + execute("get_gonio(force=" + force + ")"); + }//GEN-LAST:event_buttonGetGonioActionPerformed + + private void buttonPutGonioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPutGonioActionPerformed + String force = checkForce.isSelected() ? "True" : "False"; + execute("put_gonio(force=" + force + ")"); + }//GEN-LAST:event_buttonPutGonioActionPerformed + + private void buttonMoveParkActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveParkActionPerformed + execute("move_park()"); + }//GEN-LAST:event_buttonMoveParkActionPerformed + + private void buttonMoveHomeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveHomeActionPerformed + execute("move_home()"); + }//GEN-LAST:event_buttonMoveHomeActionPerformed + + private void buttonMoveGonioActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveGonioActionPerformed + execute("move_gonio()"); + }//GEN-LAST:event_buttonMoveGonioActionPerformed + + private void buttonMoveDewarActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveDewarActionPerformed + execute("move_dewar()"); + }//GEN-LAST:event_buttonMoveDewarActionPerformed + + private void buttonMoveScannerActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveScannerActionPerformed + execute("move_scanner()"); + }//GEN-LAST:event_buttonMoveScannerActionPerformed + + private void buttonMoveHeaterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveHeaterActionPerformed + execute("move_heater()"); + }//GEN-LAST:event_buttonMoveHeaterActionPerformed + + private void buttonDryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDryActionPerformed + double dryTime = (Double) spinnerDryTime.getValue(); + double streamTime = (Double) spinnerDrySpeed.getValue(); + boolean park = ckeckParkOnDry.isSelected(); + + execute("dry(" + dryTime + ", " + streamTime + (park ? ", wait_cold=-1": "") + ")"); + }//GEN-LAST:event_buttonDryActionPerformed + + private void buttonRecoverActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRecoverActionPerformed + execute("robot_recover()"); + }//GEN-LAST:event_buttonRecoverActionPerformed + + private void buttonMoveColdActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonMoveColdActionPerformed + execute("move_cold()"); + }//GEN-LAST:event_buttonMoveColdActionPerformed + + private void buttonClearSampleDbActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonClearSampleDbActionPerformed + execute("clear_samples_info()", true); + }//GEN-LAST:event_buttonClearSampleDbActionPerformed + + private void buttonResetPuckIdsActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonResetPuckIdsActionPerformed + execute("reset_puck_datamatrix()", true); + }//GEN-LAST:event_buttonResetPuckIdsActionPerformed + + private void buttonScanPinActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonScanPinActionPerformed + String segment = checkAuxiliary.isSelected() ? "X" : (String) spinnerSegment.getValue(); + int puck = checkAuxiliary.isSelected() ? 1 :(Integer) spinnerPuck.getValue(); + int sample = (Integer) spinnerSample.getValue(); + String force = checkForce.isSelected() ? "True" : "False"; + execute("scan_pin('" + segment + "'," + puck + "," + sample + ", force=" + force + ")", false, true); + }//GEN-LAST:event_buttonScanPinActionPerformed + + private void buttonScanPuckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonScanPuckActionPerformed + String segment = checkAuxiliary.isSelected() ? "X" : (String) spinnerSegment.getValue(); + int puck = checkAuxiliary.isSelected() ? 1 :(Integer) spinnerPuck.getValue(); + String force = checkForce.isSelected() ? "True" : "False"; + execute("scan_puck('" + segment + "'," + puck + ", force=" + force + ")", false, true); + }//GEN-LAST:event_buttonScanPuckActionPerformed + + private void buttonGetAuxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGetAuxActionPerformed + int sample = (Integer) spinnerSample.getValue(); + execute("get_aux('" + sample + ")"); + }//GEN-LAST:event_buttonGetAuxActionPerformed + + private void buttonPutAuxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPutAuxActionPerformed + int sample = (Integer) spinnerSample.getValue(); + execute("put_aux('" + sample + ")"); + }//GEN-LAST:event_buttonPutAuxActionPerformed + + private void checkAuxiliaryActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkAuxiliaryActionPerformed + onStateChange(getState(), null); + }//GEN-LAST:event_checkAuxiliaryActionPerformed + + private void buttonGripperScanActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGripperScanActionPerformed + execute("scan_gripper()"); + }//GEN-LAST:event_buttonGripperScanActionPerformed + + private void buttonTrashActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonTrashActionPerformed + execute("trash()"); + }//GEN-LAST:event_buttonTrashActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton buttonClearSampleDb; + private javax.swing.JButton buttonDry; + private javax.swing.JButton buttonEnableAll; + private javax.swing.JButton buttonGetAux; + private javax.swing.JButton buttonGetDewar; + private javax.swing.JButton buttonGetGonio; + private javax.swing.JButton buttonGripperScan; + private javax.swing.JButton buttonMount; + private javax.swing.JButton buttonMoveAux; + private javax.swing.JButton buttonMoveCold; + private javax.swing.JButton buttonMoveDewar; + private javax.swing.JButton buttonMoveGonio; + private javax.swing.JButton buttonMoveHeater; + private javax.swing.JButton buttonMoveHome; + private javax.swing.JButton buttonMovePark; + private javax.swing.JButton buttonMoveScanner; + private javax.swing.JButton buttonPutAux; + private javax.swing.JButton buttonPutDewar; + private javax.swing.JButton buttonPutGonio; + private javax.swing.JButton buttonRecover; + private javax.swing.JButton buttonResetPuckIds; + private javax.swing.JButton buttonScanPin; + private javax.swing.JButton buttonScanPuck; + private javax.swing.JButton buttonTrash; + private javax.swing.JButton buttonUnmount; + private javax.swing.JCheckBox checkAuxiliary; + private javax.swing.JCheckBox checkDatamatrix; + private javax.swing.JCheckBox checkForce; + private javax.swing.JCheckBox ckeckParkOnDry; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel5; + private javax.swing.JTabbedPane jTabbedPane1; + private javax.swing.JPanel pnDatabase; + private javax.swing.JPanel pnDry; + private javax.swing.JPanel pnLowLevel; + private javax.swing.JPanel pnMotion; + private javax.swing.JPanel pnTransfer; + private javax.swing.JSpinner spinnerDrySpeed; + private javax.swing.JSpinner spinnerDryTime; + private javax.swing.JSpinner spinnerPuck; + private javax.swing.JSpinner spinnerSample; + private javax.swing.JSpinner spinnerSegment; + private javax.swing.JPanel tabAdvanced; + private javax.swing.JPanel tabCommands; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/Hexiposi.form b/plugins/Hexiposi.form new file mode 100644 index 0000000..4687d34 --- /dev/null +++ b/plugins/Hexiposi.form @@ -0,0 +1,34 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/Hexiposi.java b/plugins/Hexiposi.java new file mode 100644 index 0000000..2c55c2c --- /dev/null +++ b/plugins/Hexiposi.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2014-2018 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.core.Context; +import ch.psi.pshell.ui.StripChart; +import ch.psi.pshell.ui.App; +import ch.psi.pshell.ui.Panel; +import ch.psi.utils.State; +import java.io.File; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + */ +public class Hexiposi extends Panel { + final StripChart stripChart; + public Hexiposi() { + initComponents(); + stripChart = new StripChart(this.getTopLevel(), false, App.getStripChartFolderArg()); + panel.add(stripChart.getPlotPanel()); + + try { + stripChart.open(new File(Context.getInstance().getSetup().expandPath("{home}/stripchart/hexiposi_positon.scd"))); + stripChart.start(); + } catch (Exception ex) { + showException(ex); + Logger.getLogger(Hexiposi.class.getName()).log(Level.WARNING, null, ex); + } + + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + + } + + @Override + public void onStateChange(State state, State former) { + + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + + //Callback to perform update - in event thread + @Override + protected void doUpdate() { + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + panel = new javax.swing.JPanel(); + + panel.setLayout(new java.awt.BorderLayout()); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel panel; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/HexiposiPanel.form b/plugins/HexiposiPanel.form new file mode 100644 index 0000000..65d0c18 --- /dev/null +++ b/plugins/HexiposiPanel.form @@ -0,0 +1,81 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/HexiposiPanel.java b/plugins/HexiposiPanel.java new file mode 100644 index 0000000..b29a526 --- /dev/null +++ b/plugins/HexiposiPanel.java @@ -0,0 +1,110 @@ + + +import ch.psi.pshell.core.Context; +import ch.psi.pshell.device.Device; +import ch.psi.pshell.swing.DevicePanel; + +/** + * + */ +public class HexiposiPanel extends DevicePanel { + + /** + * Creates new form HexiposiPositionPanel + */ + public HexiposiPanel() { + initComponents(); + } + + @Override + public void setDevice(Device device){ + super.setDevice(device); + discretePositionerPanel.setDevice(device); + } + + @Override + public void setEnabled(boolean enabled){ + super.setEnabled(enabled); + discretePositionerPanel.setEnabled(enabled); + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + discretePositionerPanel = new ch.psi.pshell.swing.DiscretePositionerPanel(); + jPanel1 = new javax.swing.JPanel(); + buttonHoming = new javax.swing.JButton(); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Initialize")); + + buttonHoming.setText("Homing"); + buttonHoming.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonHomingActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonHoming) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(buttonHoming) + .addContainerGap()) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(discretePositionerPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(discretePositionerPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// //GEN-END:initComponents + + private void buttonHomingActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonHomingActionPerformed + try { + //Context.getInstance().evalLineAsync("hexiposi.move_home()").handle((ret, ex) -> { + Context.getInstance().evalLineAsync("homing_hexiposi()").handle((ret, ex) -> { + if (ex != null){ + showException((Exception)ex); + } + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + + }//GEN-LAST:event_buttonHomingActionPerformed + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton buttonHoming; + private ch.psi.pshell.swing.DiscretePositionerPanel discretePositionerPanel; + private javax.swing.JPanel jPanel1; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/LN2.form b/plugins/LN2.form new file mode 100644 index 0000000..4687d34 --- /dev/null +++ b/plugins/LN2.form @@ -0,0 +1,34 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/LN2.java b/plugins/LN2.java new file mode 100644 index 0000000..2300e49 --- /dev/null +++ b/plugins/LN2.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2014-2018 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.core.Context; +import ch.psi.pshell.plot.TimePlotBase; +import ch.psi.pshell.ui.StripChart; +import ch.psi.pshell.ui.App; +import ch.psi.pshell.ui.Panel; +import ch.psi.utils.State; +import ch.psi.utils.swing.SwingUtils; +import java.awt.Dimension; +import java.io.File; +import java.io.IOException; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + */ +public class LN2 extends Panel { + final StripChart stripChart; + TimePlotBase plot; + public LN2() { + initComponents(); + stripChart = new StripChart(this.getTopLevel(), false, App.getStripChartFolderArg()); + panel.add(stripChart.getPlotPanel()); + + try { + stripChart.open(new File(Context.getInstance().getSetup().expandPath("{home}/stripchart/LN2_Monitoring.scd"))); + stripChart.start(); + } catch (Exception ex) { + showException(ex); + Logger.getLogger(LN2.class.getName()).log(Level.WARNING, null, ex); + } + + plot = (TimePlotBase) SwingUtils.getComponentsByType(stripChart.getPlotPanel(),TimePlotBase.class)[0]; + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + } + + + @Override + public void onStop() { + //saveImage(); + super.onStop(); + } + + @Override + public void onStateChange(State state, State former) { + if ( (state == State.Closing) || + ((state == State.Initializing) && (former != State.Invalid)) + ){ + saveImage(); + } + + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + public void saveImage(){ + getLogger().severe("Saving image"); + try { + String fileName = new File(getContext().getSetup().expandPath("{images}/ln2/{date}_{time}.png")).getCanonicalPath(); + getLogger().severe("File: " + fileName); + plot.saveSnapshot(fileName, "png", new Dimension(1200,800)); + } catch (Exception ex) { + getLogger().log(Level.SEVERE, null, ex); + } + getLogger().severe("Done"); + } + + //Callback to perform update - in event thread + @Override + protected void doUpdate() { + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + panel = new javax.swing.JPanel(); + + panel.setLayout(new java.awt.BorderLayout()); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(panel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + }// //GEN-END:initComponents + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JPanel panel; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/LaserUE.java b/plugins/LaserUE.java new file mode 100644 index 0000000..37dd6ee --- /dev/null +++ b/plugins/LaserUE.java @@ -0,0 +1,79 @@ + +import ch.psi.pshell.device.Readable; +import ch.psi.pshell.serial.SerialPortDevice; +import ch.psi.pshell.serial.SerialPortDeviceConfig; +import static ch.psi.utils.BitMask.*; +import ch.psi.utils.State; +import java.io.IOException; + +/* + * + */ + +/** + * + */ +public class LaserUE extends SerialPortDevice{ + final Readable readable; + static final double RANGE_MIN = 1.0; + static final double RANGE_MAX = 30.0; + public LaserUE(String name, String port) { + super(name, port, 921600, SerialPortDeviceConfig.DataBits.DB_8, SerialPortDeviceConfig.StopBits.SB_1, SerialPortDeviceConfig.Parity.None); + this.setMode(Mode.FullDuplex); + readable = new Readable() { + @Override + public Object read() throws IOException, InterruptedException { + return take(); + } + @Override + public String getName(){ + return LaserUE.this.getName()+"_readout"; + } + }; + } + + @Override + protected void doInitialize() throws IOException, InterruptedException{ + super.doInitialize(); + //TODO: Start DAQ in ILD1320: http://www.micro-epsilon.com/download/manuals/man--optoNCDT-1320--en.pdf + setState(State.Ready); + write("OUTPUT RS422\n\r"); + } + + public Readable getReadable(){ + return readable; + } + + int value = 0; + int count = 0; + + @Override + protected void onByte(int rx) { + int index = ((rx&BIT7) > 0) ? 2 : (((rx&BIT6) > 0) ? 1 : 0); + if (count==index){ + if (index ==0){ + value = rx & 0x3F; + count = 1; + } else if (index ==1){ + value = ((rx& 0x3F)<<6) + value; + count = 2; + } else if (index ==2){ + value = ((rx& 0x0F)<<12) + value; + double val = ((double)value)/1000; + if ((valRANGE_MAX)){ + val = Double.NaN; + } + setCache(val); + count = 0; + } else { + count = 0; + } + } + else{ + count = 0; + } + } + + + +} diff --git a/plugins/LaserUEPanel.form b/plugins/LaserUEPanel.form new file mode 100644 index 0000000..c9c5f8d --- /dev/null +++ b/plugins/LaserUEPanel.form @@ -0,0 +1,59 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/plugins/LaserUEPanel.java b/plugins/LaserUEPanel.java new file mode 100644 index 0000000..017fb77 --- /dev/null +++ b/plugins/LaserUEPanel.java @@ -0,0 +1,98 @@ +import ch.psi.pshell.core.Context; +import ch.psi.pshell.device.Device; +import ch.psi.pshell.swing.DevicePanel; +import ch.psi.utils.swing.SwingUtils; + +/** + * + */ +public class LaserUEPanel extends DevicePanel { + + public LaserUEPanel() { + initComponents(); + } + + @Override + public void setDevice(Device device){ + super.setDevice(device); + if (device!=null){ + historyChart.addDevice("Laser Distance", device); + } else { + for (Device d: historyChart.getDevices()){ + historyChart.removeDevice(device); + } + } + } + + + void execute(String statement, boolean showReturn){ + try { + Context.getInstance().evalLineBackgroundAsync(statement).handle((ret, ex) -> { + if (LaserUEPanel.this.isShowing()){ + if (ex != null){ + showException((Exception)ex); + } else if (showReturn){ + if (ret == null){ + SwingUtils.showMessage(this, "Return", "No code detected", 20000); + } else { + SwingUtils.showMessage(this, "Return", "Detected code: " +ret, 20000); + } + } + } + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + } + + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + deviceStatePanel2 = new ch.psi.pshell.swing.DeviceStatePanel(); + try { + historyChart = new ch.psi.pshell.swing.HistoryChart(); + } catch (java.lang.ClassNotFoundException e1) { + e1.printStackTrace(); + } catch (java.lang.InstantiationException e2) { + e2.printStackTrace(); + } catch (java.lang.IllegalAccessException e3) { + e3.printStackTrace(); + } + deviceValuePanel1 = new ch.psi.pshell.swing.DeviceValuePanel(); + + deviceStatePanel2.setDeviceName("ue"); + + deviceValuePanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Value")); + deviceValuePanel1.setDeviceName("ue"); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(historyChart, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addGroup(layout.createSequentialGroup() + .addComponent(deviceStatePanel2, javax.swing.GroupLayout.DEFAULT_SIZE, 297, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(deviceValuePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 297, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(historyChart, javax.swing.GroupLayout.DEFAULT_SIZE, 307, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(deviceStatePanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(deviceValuePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + ); + }// //GEN-END:initComponents + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private ch.psi.pshell.swing.DeviceStatePanel deviceStatePanel2; + private ch.psi.pshell.swing.DeviceValuePanel deviceValuePanel1; + private ch.psi.pshell.swing.HistoryChart historyChart; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/MXSC-1.10.0.jar b/plugins/MXSC-1.10.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..af678da9ad66d92b473dad63ebfd76c78c6ccfa2 GIT binary patch literal 272262 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

}L!?^%<*AriDDLlCLM&UtoVT&MmVj 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�x)cl3rT*IfD(k>& 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

MtMyqa>}#@Z8Q5_z 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�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 LGj`%pY<9vwdFZtV literal 0 HcmV?d00001 diff --git a/plugins/MjpegSource2.java b/plugins/MjpegSource2.java new file mode 100644 index 0000000..89ab9ef --- /dev/null +++ b/plugins/MjpegSource2.java @@ -0,0 +1,149 @@ + +import ch.psi.pshell.imaging.SourceBase; +import ch.psi.pshell.imaging.SourceConfig; +import ch.psi.pshell.imaging.Utils; +import java.awt.image.BufferedImage; +import java.io.BufferedInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.logging.Level; + +/** + * Image source receive frames from a mjpeg server. + */ +public class MjpegSource2 extends SourceBase { + + final String url; + final boolean flushOnUpdate; + + public MjpegSource2(String name, String url) { + this(name, url, false); + } + + public MjpegSource2(String name, String url, boolean flushOnUpdate) { + super(name, new SourceConfig()); + this.url = url; + this.flushOnUpdate = flushOnUpdate; + } + + InputStream stream; + + @Override + protected void doInitialize() throws IOException, InterruptedException { + super.doInitialize(); + URL aux = new URL(url); + stream = aux.openStream(); + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + } + + Thread monitoredThread; + + @Override + protected void doSetMonitored(boolean value) { + if (value && (monitoredThread == null)) { + monitoredThread = new Thread(() -> { + try { + while (true) { + try { + doUpdate(); + Thread.sleep(1); + } catch (IOException ex) { + getLogger().log(Level.FINE, null, ex); + } + } + } catch (InterruptedException ex) { + return; + } + }); + monitoredThread.setDaemon(true); + monitoredThread.start(); + } else if (!value && (monitoredThread != null)) { + monitoredThread.interrupt(); + monitoredThread = null; + } + } + + final byte[] START_OF_FRAME = {(byte) 0xFF, (byte) 0xD8}; + final byte[] END_OF_FRAME = {(byte) 0xFF, (byte) 0xD9}; + final int MAX_FRAME_SIZE = 512 * 1024; + + @Override + protected void doUpdate() throws IOException, InterruptedException { + byte[] data = null; + if (stream != null) { + if (flushOnUpdate) { + flush(); + } + try { + data = readData(); + } catch (EOFException ex) { + //Try to reopen stream + doInitialize(); + data = readData(); + } + } + if (data == null) { + pushImage(null); + } else { + BufferedImage img = Utils.newImage(data); + pushImage(img); + } + } + byte[] readData() throws IOException { + if (stream != null) { + stream.mark(MAX_FRAME_SIZE); + int startOfFrame = waitBytes(START_OF_FRAME) - START_OF_FRAME.length; + if (startOfFrame >= 0) { + int endOfFrame = waitBytes(END_OF_FRAME); + if (endOfFrame >= 0) { + stream.reset(); + stream.skip(startOfFrame); + int length = endOfFrame ;//- END_OF_FRAME.length ; + byte[] data = new byte[length]; + stream.read(data, 0, length); + return data; + } + } + } + return null; + } + + int waitBytes(byte[] data) throws IOException { + int index = 0; + int dataPos = 0; + while (true) { + int ret = stream.read(); + if (ret < 0) { + throw new EOFException(); + } + byte value = (byte) ret; + if (value == data[dataPos]) { + dataPos++; + if (dataPos == data.length) { + return (index + 1); + } + } else { + dataPos = 0; + } + index++; + if (index >= MAX_FRAME_SIZE) { + return -1; + } + } + } + + public void flush() throws IOException { + //stream.skip(stream.available()); + //TODO: Skipping won't make the current image to be displayed + stream.close(); + stream = new URL(url).openStream(); + if (!stream.markSupported()) { + stream = new BufferedInputStream(stream); + } + } + +} diff --git a/plugins/NewJPanel.form b/plugins/NewJPanel.form new file mode 100644 index 0000000..76577a0 --- /dev/null +++ b/plugins/NewJPanel.form @@ -0,0 +1,136 @@ + + +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/plugins/NewJPanel.java b/plugins/NewJPanel.java new file mode 100644 index 0000000..9de490b --- /dev/null +++ b/plugins/NewJPanel.java @@ -0,0 +1,217 @@ + +import ch.psi.pshell.device.Device; +import ch.psi.pshell.device.DeviceAdapter; +import ch.psi.utils.State; +import java.awt.Color; + +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author gac-S_Changer + */ +public class NewJPanel extends javax.swing.JPanel { + + /** + * Creates new form NewJPanel + */ + public NewJPanel() { + initComponents(); + + + ((Device) getDevice("hexiposi")).addListener(new DeviceAdapter() { + @Override + public void onStateChanged(Device device, State state, State former) { + updateHexiposiState(state); + } + }); + updateHexiposiState(((Device) getDevice("hexiposi")).getState()); + + ((Device) getDevice("air_pressure_ok")).addListener(new DeviceAdapter() { + @Override + public void onValueChanged(Device device, Object value, Object former) { + updateAirPressure(value); + } + }); + updateAirPressure(((Device) getDevice("air_pressure_ok")).take()); + + ((Device) getDevice("n2_pressure_ok")).addListener(new DeviceAdapter() { + @Override + public void onValueChanged(Device device, Object value, Object former) { + updateN2Pressure(value); + } + }); + updateN2Pressure(((Device) getDevice("n2_pressure_ok")).take()); + + ((Device) getDevice("feedback_local_safety")).addListener(new DeviceAdapter() { + @Override + public void onValueChanged(Device device, Object value, Object former) { + updateLocalSafety(value); + } + }); + updateLocalSafety(((Device) getDevice("feedback_local_safety")).take()); + + ((Device) getDevice("feedback_psys_safety")).addListener(new DeviceAdapter() { + @Override + public void onValueChanged(Device device, Object value, Object former) { + updatePsysSafety(value); + } + }); + updatePsysSafety(((Device) getDevice("feedback_psys_safety")).take()); + } + + void updateHexiposiState(State state){ + ledLidControlActive.setColor(state.isInitialized() ? Color.GREEN : Color.BLACK ); + ledLidInitialized.setColor((state.isNormal()&& state !=State.Disabled) ? Color.GREEN : Color.BLACK); + } + + void updateAirPressure(Object value){ + if ((value == null) || !(value instanceof Boolean)){ + ledAirPressure.setColor(Color.BLACK); + } else if ((Boolean)value){ + ledAirPressure.setColor(Color.GREEN); + } else { + ledAirPressure.setColor(Color.RED); + } + } + + void updateN2Pressure(Object value){ + if ((value == null) || !(value instanceof Boolean)){ + ledN2Pressure.setColor(Color.BLACK); + } else if ((Boolean)value){ + ledN2Pressure.setColor(Color.GREEN); + } else { + ledN2Pressure.setColor(Color.RED); + } + } + + void updateLocalSafety(Object value){ + if ((value == null) || !(value instanceof Boolean)){ + ledLocalSafety.setColor(Color.BLACK); + } else if ((Boolean)value){ + ledLocalSafety.setColor(Color.GREEN); + } else { + ledLocalSafety.setColor(Color.RED); + } + } + + void updatePsysSafety(Object value){ + if ((value == null) || !(value instanceof Boolean)){ + ledPsysSafety.setColor(Color.BLACK); + } else if ((Boolean)value){ + ledPsysSafety.setColor(Color.GREEN); + } else { + ledPsysSafety.setColor(Color.RED); + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // //GEN-BEGIN:initComponents + private void initComponents() { + + jPanel11 = new javax.swing.JPanel(); + ledAirPressure = new ch.psi.pshell.swing.Led(); + jLabel15 = new javax.swing.JLabel(); + jLabel16 = new javax.swing.JLabel(); + ledN2Pressure = new ch.psi.pshell.swing.Led(); + jLabel19 = new javax.swing.JLabel(); + ledLocalSafety = new ch.psi.pshell.swing.Led(); + jLabell20 = new javax.swing.JLabel(); + ledPsysSafety = new ch.psi.pshell.swing.Led(); + + jPanel11.setBorder(javax.swing.BorderFactory.createTitledBorder("System Status")); + + jLabel15.setText("Air Pressure"); + + jLabel16.setText("N2 Pressure"); + + jLabel19.setText("Local Safety"); + + jLabell20.setText("Psys Safety"); + + javax.swing.GroupLayout jPanel11Layout = new javax.swing.GroupLayout(jPanel11); + jPanel11.setLayout(jPanel11Layout); + jPanel11Layout.setHorizontalGroup( + jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel11Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel11Layout.createSequentialGroup() + .addComponent(ledAirPressure, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel15)) + .addGroup(jPanel11Layout.createSequentialGroup() + .addComponent(ledN2Pressure, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel16)) + .addGroup(jPanel11Layout.createSequentialGroup() + .addComponent(ledLocalSafety, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel19)) + .addGroup(jPanel11Layout.createSequentialGroup() + .addComponent(ledPsysSafety, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabell20))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel11Layout.setVerticalGroup( + jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel11Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(ledAirPressure, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel15)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(ledN2Pressure, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel16)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(ledLocalSafety, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel19)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(jPanel11Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(ledPsysSafety, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabell20))) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(163, 163, 163) + .addComponent(jPanel11, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(122, 122, 122)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(85, 85, 85) + .addComponent(jPanel11, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(83, 83, 83)) + ); + }// //GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel15; + private javax.swing.JLabel jLabel16; + private javax.swing.JLabel jLabel19; + private javax.swing.JLabel jLabell20; + private javax.swing.JPanel jPanel11; + private ch.psi.pshell.swing.Led ledAirPressure; + private ch.psi.pshell.swing.Led ledLocalSafety; + private ch.psi.pshell.swing.Led ledN2Pressure; + private ch.psi.pshell.swing.Led ledPsysSafety; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/PuckDetectionPanel.form b/plugins/PuckDetectionPanel.form new file mode 100644 index 0000000..9d644a4 --- /dev/null +++ b/plugins/PuckDetectionPanel.form @@ -0,0 +1,184 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + <Column maxWidth="-1" minWidth="-1" prefWidth="-1" resizable="true"> + <Title/> + <Editor/> + <Renderer/> + </Column> + </TableColumnModel> + </Property> + <Property name="tableHeader" type="javax.swing.table.JTableHeader" editor="org.netbeans.modules.form.editors2.JTableHeaderEditor"> + <TableHeader reorderingAllowed="true" resizingAllowed="true"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + <Component class="ch.psi.pshell.swing.DeviceStatePanel" name="deviceStatePanel1"> + <Properties> + <Property name="deviceName" type="java.lang.String" value="puck_detection"/> + </Properties> + </Component> + </SubComponents> +</Form> diff --git a/plugins/PuckDetectionPanel.java b/plugins/PuckDetectionPanel.java new file mode 100644 index 0000000..e36c4db --- /dev/null +++ b/plugins/PuckDetectionPanel.java @@ -0,0 +1,251 @@ +import ch.psi.mxsc.Puck; +import ch.psi.mxsc.PuckDetection; +import ch.psi.mxsc.PuckState; +import ch.psi.mxsc.PuckState.SwitchState; +import ch.psi.pshell.core.Context; +import ch.psi.pshell.swing.DevicePanel; +import ch.psi.utils.swing.SwingUtils; + +/** + * + */ +public class PuckDetectionPanel extends DevicePanel { + + public PuckDetectionPanel() { + initComponents(); + int row = 0; + for (String segment : new String[]{"A", "B", "C", "D", "E", "F"}){ + for (int puck=1; puck<=5; puck++){ + table.getModel().setValueAt(segment+puck, row++, 0); + } + } + } + + @Override + public PuckDetection getDevice(){ + return (PuckDetection) super.getDevice(); + } + + + @Override + protected void onDeviceCacheChanged(Object value, Object former, long timestamp, boolean arg3) { + for (int row=0; row< 30; row++){ + String name = table.getModel().getValueAt(row, 0).toString(); + //int id = row+1; + try { + Puck puck = getDevice().getPuck(name); + int id = puck.getIndex() + 1; + PuckState state = getDevice().getPuckState(id); + table.getModel().setValueAt(state.online, row, 1); + table.getModel().setValueAt((SwitchState.Off == state.mecSwitch) ? "" : String.valueOf(state.mecSwitch), row, 2); + table.getModel().setValueAt((SwitchState.Off == state.indSwitch) ? "" : String.valueOf(state.indSwitch), row, 3); + table.getModel().setValueAt(puck.getDetection() == null ? "" : puck.getDetection(), row, 4); + table.getModel().setValueAt(puck.getPuckType() == null ? "" : puck.getPuckType(), row, 5); + } catch (Exception ex) { + ex.printStackTrace(); + table.getModel().setValueAt(false, row, 1); + table.getModel().setValueAt(false, row, 2); + table.getModel().setValueAt(false, row, 3); + table.getModel().setValueAt("", row, 4); + table.getModel().setValueAt("", row, 5); + } + } + } + + void execute(String statement, boolean showReturn){ + try { + Context.getInstance().evalLineBackgroundAsync(statement).handle((ret, ex) -> { + if (ex != null){ + showException((Exception)ex); + } else if (showReturn){ + SwingUtils.showMessage(this, "Return", String.valueOf(ret)); + } + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + } + + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jPanel3 = new javax.swing.JPanel(); + buttonPuckDetCheck = new javax.swing.JButton(); + buttonPuckDetStop = new javax.swing.JButton(); + buttonPuckDetStart = new javax.swing.JButton(); + jPanel1 = new javax.swing.JPanel(); + jScrollPane1 = new javax.swing.JScrollPane(); + table = new javax.swing.JTable(); + deviceStatePanel1 = new ch.psi.pshell.swing.DeviceStatePanel(); + + jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Raspberry Pi ")); + + buttonPuckDetCheck.setText("Ckeck"); + buttonPuckDetCheck.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPuckDetCheckActionPerformed(evt); + } + }); + + buttonPuckDetStop.setText("Stop"); + buttonPuckDetStop.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPuckDetStopActionPerformed(evt); + } + }); + + buttonPuckDetStart.setText("Start"); + buttonPuckDetStart.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPuckDetStartActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addComponent(buttonPuckDetCheck) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 107, Short.MAX_VALUE) + .addComponent(buttonPuckDetStop) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 108, Short.MAX_VALUE) + .addComponent(buttonPuckDetStart) + .addContainerGap()) + ); + + jPanel3Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonPuckDetCheck, buttonPuckDetStart, buttonPuckDetStop}); + + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonPuckDetCheck) + .addComponent(buttonPuckDetStop) + .addComponent(buttonPuckDetStart)) + .addContainerGap()) + ); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Detection")); + + table.setModel(new javax.swing.table.DefaultTableModel( + new Object [][] { + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null}, + {null, null, null, null, null, null} + }, + new String [] { + "Puck", "Online", "Mechanical", "Inductive", "Detection", "Image" + } + ) { + Class[] types = new Class [] { + java.lang.String.class, java.lang.Boolean.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class + }; + boolean[] canEdit = new boolean [] { + false, false, false, false, false, false + }; + + public Class getColumnClass(int columnIndex) { + return types [columnIndex]; + } + + public boolean isCellEditable(int rowIndex, int columnIndex) { + return canEdit [columnIndex]; + } + }); + jScrollPane1.setViewportView(table); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE) + .addContainerGap()) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 274, Short.MAX_VALUE) + .addContainerGap()) + ); + + deviceStatePanel1.setDeviceName("puck_detection"); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(deviceStatePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGap(0, 0, 0) + .addComponent(deviceStatePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0)) + ); + }// </editor-fold>//GEN-END:initComponents + + private void buttonPuckDetCheckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPuckDetCheckActionPerformed + execute("check_puck_detection()", true); + }//GEN-LAST:event_buttonPuckDetCheckActionPerformed + + private void buttonPuckDetStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPuckDetStopActionPerformed + execute("stop_puck_detection()", false); + }//GEN-LAST:event_buttonPuckDetStopActionPerformed + + private void buttonPuckDetStartActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPuckDetStartActionPerformed + execute("start_puck_detection()", false); + }//GEN-LAST:event_buttonPuckDetStartActionPerformed + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton buttonPuckDetCheck; + private javax.swing.JButton buttonPuckDetStart; + private javax.swing.JButton buttonPuckDetStop; + private ch.psi.pshell.swing.DeviceStatePanel deviceStatePanel1; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel3; + private javax.swing.JScrollPane jScrollPane1; + private javax.swing.JTable table; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/Recovery.form b/plugins/Recovery.form new file mode 100644 index 0000000..e892c04 --- /dev/null +++ b/plugins/Recovery.form @@ -0,0 +1,140 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="-2" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="ledKnownPosition" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" max="-2" attributes="0"/> + <Component id="jLabel6" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" min="-2" max="-2" attributes="0"/> + <Component id="textPosition" max="32767" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="ledValidSegment" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" max="-2" attributes="0"/> + <Component id="jLabel7" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="16" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="0" pref="0" max="32767" attributes="0"/> + <Component id="jLabel8" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="textDistance" min="-2" pref="86" max="-2" attributes="0"/> + </Group> + <Component id="textSegment" max="32767" attributes="0"/> + </Group> + </Group> + </Group> + <EmptySpace min="-2" pref="8" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace pref="136" max="32767" attributes="0"/> + <Group type="103" groupAlignment="1" attributes="0"> + <Component id="buttonAbort" linkSize="1" min="-2" pref="73" max="-2" attributes="0"/> + <Component id="buttonRecover" linkSize="1" alignment="1" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace pref="144" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="ledKnownPosition" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jLabel6" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="textPosition" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="ledValidSegment" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="jLabel7" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="textSegment" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel8" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="textDistance" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace pref="81" max="32767" attributes="0"/> + <Component id="buttonRecover" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="buttonAbort" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="ch.psi.pshell.swing.Led" name="ledKnownPosition"> + </Component> + <Component class="javax.swing.JLabel" name="jLabel6"> + <Properties> + <Property name="text" type="java.lang.String" value="Known position"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledValidSegment"> + </Component> + <Component class="javax.swing.JLabel" name="jLabel7"> + <Properties> + <Property name="text" type="java.lang.String" value="Valid segment"/> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="buttonRecover"> + <Properties> + <Property name="text" type="java.lang.String" value="Recover"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonRecoverActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="buttonAbort"> + <Properties> + <Property name="text" type="java.lang.String" value="Abort"/> + <Property name="enabled" type="boolean" value="false"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonAbortActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JTextField" name="textPosition"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + </Properties> + </Component> + <Component class="javax.swing.JTextField" name="textSegment"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + </Properties> + </Component> + <Component class="javax.swing.JTextField" name="textDistance"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + <Property name="horizontalAlignment" type="int" value="11"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel8"> + <Properties> + <Property name="text" type="java.lang.String" value="Distance:"/> + </Properties> + </Component> + </SubComponents> +</Form> diff --git a/plugins/Recovery.java b/plugins/Recovery.java new file mode 100644 index 0000000..7b6381b --- /dev/null +++ b/plugins/Recovery.java @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2014-2017 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.device.Device; +import ch.psi.pshell.ui.Panel; +import ch.psi.utils.State; +import ch.psi.utils.swing.SwingUtils; +import java.awt.Color; +import java.util.List; +import javax.swing.SwingUtilities; + +/** + * + */ +public class Recovery extends Panel { + + public Recovery() { + initComponents(); + startTimer(5000, 200); + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + + } + + @Override + public void onStateChange(State state, State former) { + if (state==State.Ready){ + SwingUtilities.invokeLater(()->{onTimer();}); + } + textSegment.setEnabled(state == State.Ready); + textDistance.setEnabled(state == State.Ready); + textPosition.setEnabled(state == State.Ready); + updateButton(); + } + + void updateButton(){ + buttonRecover.setEnabled((getContext().getState() == State.Ready) && + (!textSegment.getText().trim().isEmpty()) && + (textPosition.getText().trim().isEmpty()) ); + + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + + + @Override + protected void onTimer() { + Device robot = getContext().getDevicePool().getByName("robot", Device.class); + if ((robot==null) || (!robot.getState().isNormal())){ + ledValidSegment.setColor(Color.BLACK); + textSegment.setText(""); + ledKnownPosition.setColor(Color.BLACK); + textPosition.setText(""); + } else { + if (getState()==State.Ready){ + String point = null; + try{ + point = (String) eval("robot.get_current_point()", true); + ledKnownPosition.setColor((point == null) ? Color.RED : Color.GREEN); + textPosition.setText((point == null) ? "": point); + } catch (Exception ex) { + System.out.println(ex); + ledKnownPosition.setColor(Color.BLACK); + textPosition.setText(""); + } + try{ + List segment = (List) eval("get_current_segment()", true); + ledValidSegment.setColor((segment == null) ? Color.RED : Color.GREEN); + textSegment.setText((segment == null) ? "": segment.get(0) + "->" + segment.get(1) + " [" + segment.get(2) + "mm]"); + if ((segment == null)||(point!=null)){ + textDistance.setText(""); + } else { + try{ + Object distance = eval("get_current_distance()", true); + textDistance.setText((distance == null) ? "" : String.format("%1.2f",((Number)distance).doubleValue())); + } catch (Exception ex) { + textDistance.setText(""); + } + } + } catch (Exception ex) { + System.out.println(ex); + ledValidSegment.setColor(Color.BLACK); + textSegment.setText(""); + textDistance.setText(""); + } + } + } + updateButton(); + } + + + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + ledKnownPosition = new ch.psi.pshell.swing.Led(); + jLabel6 = new javax.swing.JLabel(); + ledValidSegment = new ch.psi.pshell.swing.Led(); + jLabel7 = new javax.swing.JLabel(); + buttonRecover = new javax.swing.JButton(); + buttonAbort = new javax.swing.JButton(); + textPosition = new javax.swing.JTextField(); + textSegment = new javax.swing.JTextField(); + textDistance = new javax.swing.JTextField(); + jLabel8 = new javax.swing.JLabel(); + + jLabel6.setText("Known position"); + + jLabel7.setText("Valid segment"); + + buttonRecover.setText("Recover"); + buttonRecover.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonRecoverActionPerformed(evt); + } + }); + + buttonAbort.setText("Abort"); + buttonAbort.setEnabled(false); + buttonAbort.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonAbortActionPerformed(evt); + } + }); + + textPosition.setEditable(false); + + textSegment.setEditable(false); + + textDistance.setEditable(false); + textDistance.setHorizontalAlignment(javax.swing.JTextField.TRAILING); + + jLabel8.setText("Distance:"); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(ledKnownPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel6) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(textPosition)) + .addGroup(layout.createSequentialGroup() + .addComponent(ledValidSegment, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel7) + .addGap(16, 16, 16) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(0, 0, Short.MAX_VALUE) + .addComponent(jLabel8) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(textDistance, javax.swing.GroupLayout.PREFERRED_SIZE, 86, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(textSegment)))) + .addGap(8, 8, 8)) + .addGroup(layout.createSequentialGroup() + .addContainerGap(136, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addComponent(buttonAbort, javax.swing.GroupLayout.PREFERRED_SIZE, 73, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(buttonRecover)) + .addContainerGap(144, Short.MAX_VALUE)) + ); + + layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonAbort, buttonRecover}); + + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(ledKnownPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel6) + .addComponent(textPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(ledValidSegment, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel7) + .addComponent(textSegment, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel8) + .addComponent(textDistance, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 81, Short.MAX_VALUE) + .addComponent(buttonRecover) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonAbort) + .addContainerGap()) + ); + }// </editor-fold>//GEN-END:initComponents + + private void buttonRecoverActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonRecoverActionPerformed + try{ + buttonAbort.setEnabled(true); + evalAsync("recover()", false).handle((ret, ex) -> { + if (ex != null){ + showException((Exception)ex); + } else { + SwingUtils.showMessage(getTopLevel(), "Return", String.valueOf(ret)); + } + buttonAbort.setEnabled(false); + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + }//GEN-LAST:event_buttonRecoverActionPerformed + + private void buttonAbortActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAbortActionPerformed + try { + abort(); + try{ + eval("robot.disable()", true); + } catch (Exception ex){ + this.showException(ex); + } + try{ + eval("stop_task()", true); + } catch (Exception ex){ + this.showException(ex); + } + try{ + eval("robot.reset_motion()", true); + } catch (Exception ex){ + this.showException(ex); + } + } catch (InterruptedException ex) { + showException(ex); + } + }//GEN-LAST:event_buttonAbortActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton buttonAbort; + private javax.swing.JButton buttonRecover; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private ch.psi.pshell.swing.Led ledKnownPosition; + private ch.psi.pshell.swing.Led ledValidSegment; + private javax.swing.JTextField textDistance; + private javax.swing.JTextField textPosition; + private javax.swing.JTextField textSegment; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/RobotModbus.java b/plugins/RobotModbus.java new file mode 100644 index 0000000..ca2e149 --- /dev/null +++ b/plugins/RobotModbus.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.device.*; +import ch.psi.pshell.modbus.*; + +/** + */ +public class RobotModbus extends ModbusTCP { + + public RobotModbus(String name, String server) { + super(name, server); + } + + public Object run() throws Exception{ + Thread.sleep(1000); + return ("Done run"); + } + +} diff --git a/plugins/RobotPanel.form b/plugins/RobotPanel.form new file mode 100644 index 0000000..bf9c0d6 --- /dev/null +++ b/plugins/RobotPanel.form @@ -0,0 +1,587 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jPanel1" max="32767" attributes="0"/> + <Component id="jPanel2" alignment="0" max="32767" attributes="0"/> + <Component id="jPanel3" alignment="0" max="32767" attributes="0"/> + <Component id="panelState" alignment="0" max="32767" attributes="0"/> + <Component id="jPanel4" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jPanel1" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="jPanel4" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="jPanel2" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="jPanel3" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="panelState" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="jPanel1"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Power"/> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jLabel1" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledPowered" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="panelPowerCtr" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="4" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel1" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledPowered" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="panelPowerCtr" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="ch.psi.pshell.swing.Led" name="ledPowered"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel1"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Powered:"/> + </Properties> + </Component> + <Container class="javax.swing.JPanel" name="panelPowerCtr"> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="buttonEnable" min="-2" max="-2" attributes="0"/> + <EmptySpace pref="18" max="32767" attributes="0"/> + <Component id="buttonDisable" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Group type="103" alignment="2" groupAlignment="1" max="-2" attributes="0"> + <Component id="buttonDisable" alignment="1" max="32767" attributes="0"/> + <Component id="buttonEnable" alignment="1" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="buttonDisable"> + <Properties> + <Property name="text" type="java.lang.String" value="Disable"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonDisableActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="buttonEnable"> + <Properties> + <Property name="text" type="java.lang.String" value="Enable"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonEnableActionPerformed"/> + </Events> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel2"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Motion"/> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <Component id="jLabel7" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledMoving" min="-2" max="-2" attributes="0"/> + </Group> + <Component id="jLabel2" alignment="0" min="-2" pref="52" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="14" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" max="-2" attributes="0"> + <Component id="panelMotionCtr" max="32767" attributes="0"/> + <Component id="spinnerSpeed" max="32767" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="-2" pref="4" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel7" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledMoving" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="panelMotionCtr" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="jLabel2" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="spinnerSpeed" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="jLabel2"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Speed:"/> + </Properties> + </Component> + <Component class="javax.swing.JSpinner" name="spinnerSpeed"> + <Properties> + <Property name="model" type="javax.swing.SpinnerModel" editor="org.netbeans.modules.form.editors2.SpinnerModelEditor"> + <SpinnerModel initial="10" maximum="100" numberType="java.lang.Integer" stepSize="1" type="number"/> + </Property> + </Properties> + <Events> + <EventHandler event="stateChanged" listener="javax.swing.event.ChangeListener" parameters="javax.swing.event.ChangeEvent" handler="spinnerSpeedStateChanged"/> + </Events> + <AuxValues> + <AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ch.psi.utils.swing.HorizontalSpinner()"/> + </AuxValues> + </Component> + <Component class="javax.swing.JLabel" name="jLabel7"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Moving:"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledMoving"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Container class="javax.swing.JPanel" name="panelMotionCtr"> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="-2" pref="0" max="-2" attributes="0"/> + <Component id="butonStop" pref="45" max="32767" attributes="0"/> + <EmptySpace min="-2" max="-2" attributes="0"/> + <Component id="buttonPause" pref="46" max="32767" attributes="0"/> + <EmptySpace min="-2" max="-2" attributes="0"/> + <Component id="buttonResume" pref="47" max="32767" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="-2" pref="0" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="butonStop" alignment="2" max="32767" attributes="0"/> + <Component id="buttonPause" alignment="2" max="32767" attributes="0"/> + <Component id="buttonResume" alignment="2" max="32767" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="0" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="butonStop"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> + <Connection code="new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Stop.png"))" type="code"/> + </Property> + <Property name="text" type="java.lang.String" value=" "/> + <Property name="horizontalTextPosition" type="int" value="0"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="butonStopActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="buttonResume"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> + <Connection code="new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Play.png"))" type="code"/> + </Property> + <Property name="text" type="java.lang.String" value=" "/> + <Property name="horizontalTextPosition" type="int" value="0"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonResumeActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="buttonPause"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> + <Connection code="new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Pause.png"))" type="code"/> + </Property> + <Property name="text" type="java.lang.String" value=" "/> + <Property name="horizontalTextPosition" type="int" value="0"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonPauseActionPerformed"/> + </Events> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel3"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Status"/> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="-2" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel8" linkSize="2" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledTask" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="103" alignment="0" groupAlignment="1" attributes="0"> + <Group type="102" attributes="0"> + <Component id="jLabel4" linkSize="2" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledEmpty" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="1" attributes="0"> + <Component id="jLabel3" linkSize="2" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledSettled" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <Group type="102" attributes="0"> + <Component id="jLabel9" linkSize="2" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledPosition" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="textTask" max="32767" attributes="0"/> + <Component id="textPosition" max="32767" attributes="0"/> + </Group> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel6" linkSize="2" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledMode" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="textMode" max="32767" attributes="0"/> + </Group> + </Group> + <EmptySpace min="-2" max="-2" attributes="0"/> + <Component id="buttonAbort" min="-2" max="-2" attributes="0"/> + <EmptySpace min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace min="-2" pref="4" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel3" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledSettled" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="2" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel4" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledEmpty" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="2" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="textMode" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledMode" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="jLabel6" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="2" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="buttonAbort" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="jLabel8" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledTask" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="textTask" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="2" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel9" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledPosition" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="textPosition" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="jLabel3"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Settled:"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledSettled"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel4"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Empty:"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledEmpty"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JTextField" name="textTask"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + <Property name="horizontalAlignment" type="int" value="0"/> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel6"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Mode:"/> + </Properties> + </Component> + <Component class="javax.swing.JTextField" name="textMode"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + <Property name="horizontalAlignment" type="int" value="0"/> + </Properties> + </Component> + <Component class="javax.swing.JButton" name="buttonAbort"> + <Properties> + <Property name="text" type="java.lang.String" value="Abort"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonAbortActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JLabel" name="jLabel8"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Task:"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledTask"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledMode"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JTextField" name="textPosition"> + <Properties> + <Property name="editable" type="boolean" value="false"/> + <Property name="horizontalAlignment" type="int" value="0"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledPosition"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel9"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Position:"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="ch.psi.pshell.swing.DeviceStatePanel" name="panelState"> + </Component> + <Container class="javax.swing.JPanel" name="jPanel4"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Tool"/> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jLabel5" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledOpen" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="panelPowerCtr1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="4" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel5" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledOpen" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="panelPowerCtr1" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="-2" pref="2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="ch.psi.pshell.swing.Led" name="ledOpen"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel5"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Open:"/> + </Properties> + </Component> + <Container class="javax.swing.JPanel" name="panelPowerCtr1"> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="buttonOpen" linkSize="3" min="-2" max="-2" attributes="0"/> + <EmptySpace pref="18" max="32767" attributes="0"/> + <Component id="buttonClose" linkSize="3" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Group type="103" alignment="2" groupAlignment="1" max="-2" attributes="0"> + <Component id="buttonClose" alignment="1" max="32767" attributes="0"/> + <Component id="buttonOpen" alignment="1" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="buttonClose"> + <Properties> + <Property name="text" type="java.lang.String" value=" Close "/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonCloseActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="buttonOpen"> + <Properties> + <Property name="text" type="java.lang.String" value=" Open "/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonOpenActionPerformed"/> + </Events> + </Component> + </SubComponents> + </Container> + </SubComponents> + </Container> + </SubComponents> +</Form> diff --git a/plugins/RobotPanel.java b/plugins/RobotPanel.java new file mode 100644 index 0000000..e841f57 --- /dev/null +++ b/plugins/RobotPanel.java @@ -0,0 +1,685 @@ + +import ch.psi.pshell.device.Device; +import ch.psi.pshell.ui.App; +import ch.psi.pshell.swing.DevicePanel; +import ch.psi.pshell.core.Context; +import ch.psi.utils.State; +import java.awt.Color; +import java.util.Map; +import javax.swing.JSpinner; +import javax.swing.JTextField; + +/** + * + */ +public class RobotPanel extends DevicePanel { + + /** + * Creates new form RobotPanel + */ + public RobotPanel() { + initComponents(); + ((JSpinner.DefaultEditor)spinnerSpeed.getEditor()).getTextField().setHorizontalAlignment(JTextField.CENTER); + } + + @Override + public void setDevice(Device device) { + super.setDevice(device); + if (device == null) { + + } + panelState.setDevice(device); + } + + @Override + protected void onDeviceStateChanged(State state, State former) { + boolean enabled = state.isNormal(); + spinnerSpeed.setEnabled(enabled); + buttonAbort.setEnabled(enabled); + if (!enabled){ + buttonEnable.setEnabled(enabled); + buttonDisable.setEnabled(enabled); + butonStop.setEnabled(enabled); + buttonPause.setEnabled(enabled); + buttonResume.setEnabled(enabled); + } + } + + boolean updating; + @Override + protected void onDeviceCacheChanged(Object value, Object former, long timestamp, boolean valueChange) { + updating = true; + try{ + Boolean powered = null; + Boolean empty = null; + Boolean settled = null; + Boolean moving = null; + Boolean open = null; + Integer speed = null; + String task = null; + String mode = null; + String position = null; + + if ((value != null) && (value instanceof Map)) { + Map status = (Map) value; + try { + powered = (Boolean) status.get("powered"); + } catch (Exception ex) { + } + try { + empty = (Boolean) status.get("empty"); + } catch (Exception ex) { + } + try { + settled = (Boolean) status.get("settled"); + } catch (Exception ex) { + } + try { + open = (Boolean) status.get("open"); + } catch (Exception ex) { + } + try { + speed = (Integer) status.get("speed"); + } catch (Exception ex) { + } + try { + position = (String) status.get("pos"); + if (position==null){ + position = ""; + } + } catch (Exception ex) { + } + try { + task = ((status.containsKey("task")) && (status.get("task") == null)) ? "" : ((String) status.get("task")).trim(); + } catch (Exception ex) { + System.out.println(ex); + ex.printStackTrace(); + } + try { + mode = ((String) status.get("mode")).trim(); + //mode = (String) Context.getInstance().evalLineBackground(getDevice().getName() + ".working_mode"); + } catch (Exception ex) { + } + try { + //if (status.get("status").equals("hold")){ + // moving = false; + //} else if (status.get("status").equals("move")){ + // moving = true; + //} + moving = Boolean.FALSE.equals(settled) || Boolean.FALSE.equals(empty); + } catch (Exception ex) { + } + } + + boolean remote = mode.equals("remote"); + boolean enabled = Boolean.TRUE.equals(powered); + buttonEnable.setEnabled((powered != null) && (powered == false)); + buttonDisable.setEnabled(enabled); + + butonStop.setEnabled(remote && Boolean.TRUE.equals(moving)); + buttonPause.setEnabled(remote && enabled && Boolean.TRUE.equals(moving) && Boolean.FALSE.equals(settled)); + buttonResume.setEnabled(remote && enabled && Boolean.TRUE.equals(moving) && Boolean.TRUE.equals(settled)); + + + ledPowered.setColor((powered == null) ? Color.GRAY : (powered ? Color.YELLOW : Color.DARK_GRAY)); + ledEmpty.setColor((empty == null) ? Color.GRAY : (empty ? Color.GREEN : Color.YELLOW)); + ledSettled.setColor((settled == null) ? Color.GRAY : (settled ? Color.GREEN : Color.YELLOW)); + ledOpen.setColor((open == null) ? Color.GRAY : (open ? Color.GREEN : Color.DARK_GRAY)); + ledMoving.setColor((moving == null) ? Color.GRAY : (moving ? Color.YELLOW : Color.DARK_GRAY)); + textTask.setText((task == null) ? "" : task); + ledTask.setColor((task == null) ? Color.GRAY : (task.isEmpty() ? Color.DARK_GRAY : Color.YELLOW)); + textPosition.setText((position == null) ? "" : position); + ledPosition.setColor((position == null) ? Color.GRAY : (position.isEmpty() ? Color.DARK_GRAY : Color.GREEN)); + //buttonAbort.setEnabled(!textTask.getText().isEmpty()); + spinnerSpeed.setEnabled(speed != null); + if (speed == null) { + spinnerSpeed.setValue(0); + } else { + spinnerSpeed.setValue(speed); + } + ledMode.setColor((mode == null) ? Color.BLACK : (remote ? Color.GREEN : Color.YELLOW)); + textMode.setText((mode == null) ? "" : mode); + + } finally{ + updating = false; + } + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + ledPowered = new ch.psi.pshell.swing.Led(); + jLabel1 = new javax.swing.JLabel(); + panelPowerCtr = new javax.swing.JPanel(); + buttonDisable = new javax.swing.JButton(); + buttonEnable = new javax.swing.JButton(); + jPanel2 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + spinnerSpeed = new ch.psi.utils.swing.HorizontalSpinner(); + jLabel7 = new javax.swing.JLabel(); + ledMoving = new ch.psi.pshell.swing.Led(); + panelMotionCtr = new javax.swing.JPanel(); + butonStop = new javax.swing.JButton(); + buttonResume = new javax.swing.JButton(); + buttonPause = new javax.swing.JButton(); + jPanel3 = new javax.swing.JPanel(); + jLabel3 = new javax.swing.JLabel(); + ledSettled = new ch.psi.pshell.swing.Led(); + jLabel4 = new javax.swing.JLabel(); + ledEmpty = new ch.psi.pshell.swing.Led(); + textTask = new javax.swing.JTextField(); + jLabel6 = new javax.swing.JLabel(); + textMode = new javax.swing.JTextField(); + buttonAbort = new javax.swing.JButton(); + jLabel8 = new javax.swing.JLabel(); + ledTask = new ch.psi.pshell.swing.Led(); + ledMode = new ch.psi.pshell.swing.Led(); + textPosition = new javax.swing.JTextField(); + ledPosition = new ch.psi.pshell.swing.Led(); + jLabel9 = new javax.swing.JLabel(); + panelState = new ch.psi.pshell.swing.DeviceStatePanel(); + jPanel4 = new javax.swing.JPanel(); + ledOpen = new ch.psi.pshell.swing.Led(); + jLabel5 = new javax.swing.JLabel(); + panelPowerCtr1 = new javax.swing.JPanel(); + buttonClose = new javax.swing.JButton(); + buttonOpen = new javax.swing.JButton(); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Power")); + + ledPowered.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel1.setText("Powered:"); + + buttonDisable.setText("Disable"); + buttonDisable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonDisableActionPerformed(evt); + } + }); + + buttonEnable.setText("Enable"); + buttonEnable.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonEnableActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelPowerCtrLayout = new javax.swing.GroupLayout(panelPowerCtr); + panelPowerCtr.setLayout(panelPowerCtrLayout); + panelPowerCtrLayout.setHorizontalGroup( + panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(buttonEnable) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) + .addComponent(buttonDisable)) + ); + panelPowerCtrLayout.setVerticalGroup( + panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(buttonDisable, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonEnable)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledPowered, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(panelPowerCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel1) + .addComponent(ledPowered, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelPowerCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Motion")); + + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel2.setText("Speed:"); + + spinnerSpeed.setModel(new javax.swing.SpinnerNumberModel(10, null, 100, 1)); + spinnerSpeed.addChangeListener(new javax.swing.event.ChangeListener() { + public void stateChanged(javax.swing.event.ChangeEvent evt) { + spinnerSpeedStateChanged(evt); + } + }); + + jLabel7.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel7.setText("Moving:"); + + ledMoving.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + butonStop.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Stop.png"))); + butonStop.setText(" "); + butonStop.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + butonStop.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + butonStopActionPerformed(evt); + } + }); + + buttonResume.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Play.png"))); + buttonResume.setText(" "); + buttonResume.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonResume.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonResumeActionPerformed(evt); + } + }); + + buttonPause.setIcon(new javax.swing.ImageIcon(App.class.getResource("/ch/psi/pshell/ui/Pause.png"))); + buttonPause.setText(" "); + buttonPause.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + buttonPause.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonPauseActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelMotionCtrLayout = new javax.swing.GroupLayout(panelMotionCtr); + panelMotionCtr.setLayout(panelMotionCtrLayout); + panelMotionCtrLayout.setHorizontalGroup( + panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelMotionCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(butonStop, javax.swing.GroupLayout.DEFAULT_SIZE, 45, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonPause, javax.swing.GroupLayout.DEFAULT_SIZE, 46, Short.MAX_VALUE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonResume, javax.swing.GroupLayout.DEFAULT_SIZE, 47, Short.MAX_VALUE) + .addGap(0, 0, 0)) + ); + panelMotionCtrLayout.setVerticalGroup( + panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelMotionCtrLayout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelMotionCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(butonStop, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonPause, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonResume, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addComponent(jLabel7, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledMoving, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addComponent(jLabel2, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(14, 14, 14) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(panelMotionCtr, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(spinnerSpeed)) + .addContainerGap()) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel7) + .addComponent(ledMoving, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelMotionCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(jLabel2) + .addComponent(spinnerSpeed, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel3.setBorder(javax.swing.BorderFactory.createTitledBorder("Status")); + + jLabel3.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel3.setText("Settled:"); + + ledSettled.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel4.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel4.setText("Empty:"); + + ledEmpty.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + textTask.setEditable(false); + textTask.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + jLabel6.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel6.setText("Mode:"); + + textMode.setEditable(false); + textMode.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + buttonAbort.setText("Abort"); + buttonAbort.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonAbortActionPerformed(evt); + } + }); + + jLabel8.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel8.setText("Task:"); + + ledTask.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + ledMode.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + textPosition.setEditable(false); + textPosition.setHorizontalAlignment(javax.swing.JTextField.CENTER); + + ledPosition.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel9.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel9.setText("Position:"); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel8, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel4, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledEmpty, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledSettled, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel9, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(textTask) + .addComponent(textPosition))) + .addGroup(jPanel3Layout.createSequentialGroup() + .addComponent(jLabel6, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(textMode))) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(buttonAbort) + .addContainerGap()) + ); + + jPanel3Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {jLabel3, jLabel4, jLabel6, jLabel8, jLabel9}); + + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel3) + .addComponent(ledSettled, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel4) + .addComponent(ledEmpty, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(textMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(ledMode, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(jLabel6)) + .addGap(2, 2, 2) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(buttonAbort) + .addComponent(jLabel8) + .addComponent(ledTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(textTask, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2) + .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel9) + .addComponent(ledPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(textPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + jPanel4.setBorder(javax.swing.BorderFactory.createTitledBorder("Tool")); + + ledOpen.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel5.setText("Open:"); + + buttonClose.setText(" Close "); + buttonClose.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonCloseActionPerformed(evt); + } + }); + + buttonOpen.setText(" Open "); + buttonOpen.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonOpenActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelPowerCtr1Layout = new javax.swing.GroupLayout(panelPowerCtr1); + panelPowerCtr1.setLayout(panelPowerCtr1Layout); + panelPowerCtr1Layout.setHorizontalGroup( + panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtr1Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addComponent(buttonOpen) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 18, Short.MAX_VALUE) + .addComponent(buttonClose)) + ); + + panelPowerCtr1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonClose, buttonOpen}); + + panelPowerCtr1Layout.setVerticalGroup( + panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelPowerCtr1Layout.createSequentialGroup() + .addGap(0, 0, 0) + .addGroup(panelPowerCtr1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false) + .addComponent(buttonClose, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonOpen)) + .addGap(0, 0, 0)) + ); + + javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4); + jPanel4.setLayout(jPanel4Layout); + jPanel4Layout.setHorizontalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledOpen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(panelPowerCtr1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel4Layout.setVerticalGroup( + jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel4Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel5) + .addComponent(ledOpen, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelPowerCtr1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGap(2, 2, 2)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel3, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelState, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel4, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jPanel4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(panelState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// </editor-fold>//GEN-END:initComponents + + private void buttonEnableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonEnableActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".enable()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonEnableActionPerformed + + private void buttonDisableActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonDisableActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".disable()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonDisableActionPerformed + + private void spinnerSpeedStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_spinnerSpeedStateChanged + try{ + if (!updating){ + Context.getInstance().evalLineBackground(getDevice().getName() + ".set_monitor_speed(" + spinnerSpeed.getValue() + ")"); + } + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_spinnerSpeedStateChanged + + private void butonStopActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_butonStopActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".reset_motion()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_butonStopActionPerformed + + private void buttonPauseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonPauseActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".stop()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonPauseActionPerformed + + private void buttonResumeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonResumeActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".resume()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonResumeActionPerformed + + private void buttonAbortActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAbortActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".stop_task()"); + //Context.getInstance().evalLineBackground(getDevice().getName() + ".task_kill('" + textTask.getText() + "')"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonAbortActionPerformed + + private void buttonCloseActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonCloseActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".close_tool()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonCloseActionPerformed + + private void buttonOpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonOpenActionPerformed + try{ + Context.getInstance().evalLineBackground(getDevice().getName() + ".open_tool()"); + } catch (Exception ex){ + this.showException(ex); + } + }//GEN-LAST:event_buttonOpenActionPerformed + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton butonStop; + private javax.swing.JButton buttonAbort; + private javax.swing.JButton buttonClose; + private javax.swing.JButton buttonDisable; + private javax.swing.JButton buttonEnable; + private javax.swing.JButton buttonOpen; + private javax.swing.JButton buttonPause; + private javax.swing.JButton buttonResume; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JLabel jLabel4; + private javax.swing.JLabel jLabel5; + private javax.swing.JLabel jLabel6; + private javax.swing.JLabel jLabel7; + private javax.swing.JLabel jLabel8; + private javax.swing.JLabel jLabel9; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private javax.swing.JPanel jPanel3; + private javax.swing.JPanel jPanel4; + private ch.psi.pshell.swing.Led ledEmpty; + private ch.psi.pshell.swing.Led ledMode; + private ch.psi.pshell.swing.Led ledMoving; + private ch.psi.pshell.swing.Led ledOpen; + private ch.psi.pshell.swing.Led ledPosition; + private ch.psi.pshell.swing.Led ledPowered; + private ch.psi.pshell.swing.Led ledSettled; + private ch.psi.pshell.swing.Led ledTask; + private javax.swing.JPanel panelMotionCtr; + private javax.swing.JPanel panelPowerCtr; + private javax.swing.JPanel panelPowerCtr1; + private ch.psi.pshell.swing.DeviceStatePanel panelState; + private javax.swing.JSpinner spinnerSpeed; + private javax.swing.JTextField textMode; + private javax.swing.JTextField textPosition; + private javax.swing.JTextField textTask; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/RobotTcp.java b/plugins/RobotTcp.java new file mode 100644 index 0000000..d3f4c33 --- /dev/null +++ b/plugins/RobotTcp.java @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.device.*; +import ch.psi.pshell.serial.*; + +/** + */ +public class RobotTcp extends TcpDevice { + + public RobotTcp(String name, String server) { + super(name, server); + } + + public Object run() throws Exception{ + Thread.sleep(1000); + return ("Done"); + } + +} diff --git a/plugins/SmartMagnetConfig.java b/plugins/SmartMagnetConfig.java new file mode 100644 index 0000000..2c6213c --- /dev/null +++ b/plugins/SmartMagnetConfig.java @@ -0,0 +1,14 @@ + +import ch.psi.pshell.device.DeviceConfig; + +/** + * + */ +public class SmartMagnetConfig extends DeviceConfig{ + public double holdingCurrent; + public double restingCurrent; + public double mountCurrent; + public double unmountCurrent; + public double remanenceCurrent; + +} diff --git a/plugins/SmartMagnetPanel.form b/plugins/SmartMagnetPanel.form new file mode 100644 index 0000000..f9de056 --- /dev/null +++ b/plugins/SmartMagnetPanel.form @@ -0,0 +1,221 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jPanel1" max="32767" attributes="0"/> + <Component id="panelState" alignment="0" max="32767" attributes="0"/> + <Group type="103" groupAlignment="0" max="-2" attributes="0"> + <Component id="panelCurrent" max="32767" attributes="0"/> + <Component id="jPanel2" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jPanel1" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="panelCurrent" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="jPanel2" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="panelState" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="jPanel1"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Status"/> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel1" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledStatus" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="panelPowerCtr" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel5" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledMounted" min="-2" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel10" min="-2" pref="52" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="panelCurrentRb" min="-2" pref="173" max="-2" attributes="0"/> + </Group> + </Group> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="4" max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel1" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledStatus" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="panelPowerCtr" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel5" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledMounted" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jLabel10" min="-2" max="-2" attributes="0"/> + <Component id="panelCurrentRb" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="ch.psi.pshell.swing.Led" name="ledStatus"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel1"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Status:"/> + </Properties> + </Component> + <Container class="javax.swing.JPanel" name="panelPowerCtr"> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <EmptySpace min="0" pref="150" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <EmptySpace min="0" pref="23" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + </Layout> + </Container> + <Component class="javax.swing.JLabel" name="jLabel5"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Mounted:"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledMounted"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel10"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Current:"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.DeviceValuePanel" name="panelCurrentRb"> + <Properties> + <Property name="deviceName" type="java.lang.String" value="smc_current_rb"/> + </Properties> + </Component> + </SubComponents> + </Container> + <Component class="ch.psi.pshell.swing.DeviceStatePanel" name="panelState"> + </Component> + <Component class="ch.psi.pshell.swing.ProcessVariablePanel" name="panelCurrent"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Current"/> + </Border> + </Property> + <Property name="deviceName" type="java.lang.String" value="smc_current"/> + </Properties> + </Component> + <Container class="javax.swing.JPanel" name="jPanel2"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Gonio"/> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jLabel2" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="ledMountPosition" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="2" attributes="0"> + <Component id="jLabel2" alignment="2" min="-2" max="-2" attributes="0"/> + <Component id="ledMountPosition" alignment="2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="jLabel2"> + <Properties> + <Property name="horizontalAlignment" type="int" value="11"/> + <Property name="text" type="java.lang.String" value="Mount Position:"/> + </Properties> + </Component> + <Component class="ch.psi.pshell.swing.Led" name="ledMountPosition"> + <Properties> + <Property name="font" type="java.awt.Font" editor="org.netbeans.beaninfo.editors.FontEditor"> + <Font name="SansSerif" size="18" style="0"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + </SubComponents> +</Form> diff --git a/plugins/SmartMagnetPanel.java b/plugins/SmartMagnetPanel.java new file mode 100644 index 0000000..2108837 --- /dev/null +++ b/plugins/SmartMagnetPanel.java @@ -0,0 +1,234 @@ + +import ch.psi.pshell.device.Device; +import ch.psi.pshell.ui.App; +import ch.psi.pshell.swing.DevicePanel; +import ch.psi.pshell.core.Context; +import ch.psi.utils.State; +import java.awt.Color; +import java.lang.reflect.Method; +import java.util.Map; + +/** + * + */ +public class SmartMagnetPanel extends DevicePanel { + + /** + * Creates new form RobotPanel + */ + public SmartMagnetPanel() { + initComponents(); + } + + @Override + public void setDevice(Device device) { + super.setDevice(device); + if (device == null) { + + } + panelState.setDevice(device); + this.startTimer(1000, 100); + } + + @Override + protected void onTimer(){ + Color color = Color.RED; + try{ + if (Context.getInstance().evalLineBackground("in_mount_position").equals(Boolean.TRUE)){ + color = Color.GREEN; + } + } catch (Exception ex){ + } + ledMountPosition.setColor(color); + } + + @Override + protected void onDeviceStateChanged(State state, State former) { + switch(state){ + case Ready: + ledStatus.setColor(Color.GREEN); + ledMounted.setColor(Color.GREEN); + break; + case Busy: + ledStatus.setColor(Color.GREEN); + ledMounted.setColor(Color.ORANGE); + break; + case Fault: + ledStatus.setColor(Color.RED); + ledMounted.setColor(Color.RED); + break; + default: + ledStatus.setColor(Color.BLACK); + ledMounted.setColor(Color.BLACK); + break; + } + } + + @Override + protected void onDeviceCacheChanged(Object value, Object former, long timestamp, boolean valueChange) { + } + + /** + * This method is called from within the constructor to initialize the form. + * WARNING: Do NOT modify this code. The content of this method is always + * regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + ledStatus = new ch.psi.pshell.swing.Led(); + jLabel1 = new javax.swing.JLabel(); + panelPowerCtr = new javax.swing.JPanel(); + jLabel5 = new javax.swing.JLabel(); + ledMounted = new ch.psi.pshell.swing.Led(); + jLabel10 = new javax.swing.JLabel(); + panelCurrentRb = new ch.psi.pshell.swing.DeviceValuePanel(); + panelState = new ch.psi.pshell.swing.DeviceStatePanel(); + panelCurrent = new ch.psi.pshell.swing.ProcessVariablePanel(); + jPanel2 = new javax.swing.JPanel(); + jLabel2 = new javax.swing.JLabel(); + ledMountPosition = new ch.psi.pshell.swing.Led(); + + jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Status")); + + ledStatus.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel1.setText("Status:"); + + javax.swing.GroupLayout panelPowerCtrLayout = new javax.swing.GroupLayout(panelPowerCtr); + panelPowerCtr.setLayout(panelPowerCtrLayout); + panelPowerCtrLayout.setHorizontalGroup( + panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 150, Short.MAX_VALUE) + ); + panelPowerCtrLayout.setVerticalGroup( + panelPowerCtrLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGap(0, 23, Short.MAX_VALUE) + ); + + jLabel5.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel5.setText("Mounted:"); + + ledMounted.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + jLabel10.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel10.setText("Current:"); + + panelCurrentRb.setDeviceName("smc_current_rb"); + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel1, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledStatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(panelPowerCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel5, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledMounted, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel10, javax.swing.GroupLayout.PREFERRED_SIZE, 52, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(panelCurrentRb, javax.swing.GroupLayout.PREFERRED_SIZE, 173, javax.swing.GroupLayout.PREFERRED_SIZE))) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addGap(4, 4, 4) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel1) + .addComponent(ledStatus, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addComponent(panelPowerCtr, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel5) + .addComponent(ledMounted, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel10) + .addComponent(panelCurrentRb, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + panelCurrent.setBorder(javax.swing.BorderFactory.createTitledBorder("Current")); + panelCurrent.setDeviceName("smc_current"); + + jPanel2.setBorder(javax.swing.BorderFactory.createTitledBorder("Gonio")); + + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jLabel2.setText("Mount Position:"); + + ledMountPosition.setFont(new java.awt.Font("SansSerif", 0, 18)); // NOI18N + + javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2); + jPanel2.setLayout(jPanel2Layout); + jPanel2Layout.setHorizontalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel2) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(ledMountPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel2Layout.setVerticalGroup( + jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel2Layout.createSequentialGroup() + .addContainerGap() + .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER) + .addComponent(jLabel2) + .addComponent(ledMountPosition, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap()) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelState, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false) + .addComponent(panelCurrent, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(panelCurrent, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(panelState, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// </editor-fold>//GEN-END:initComponents + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel10; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel5; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel2; + private ch.psi.pshell.swing.Led ledMountPosition; + private ch.psi.pshell.swing.Led ledMounted; + private ch.psi.pshell.swing.Led ledStatus; + private ch.psi.pshell.swing.ProcessVariablePanel panelCurrent; + private ch.psi.pshell.swing.DeviceValuePanel panelCurrentRb; + private javax.swing.JPanel panelPowerCtr; + private ch.psi.pshell.swing.DeviceStatePanel panelState; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/TestZMQ.java b/plugins/TestZMQ.java new file mode 100644 index 0000000..cec2c40 --- /dev/null +++ b/plugins/TestZMQ.java @@ -0,0 +1,26 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/** + * + * @author gac-S_Changer + */ +public class TestZMQ { + public static void main(String[] args) { + String server = "raspberrypi:5556"; + org.zeromq.ZMQ.Context context = org.zeromq.ZMQ.context(1); + org.zeromq.ZMQ.Socket subscriber = context.socket(org.zeromq.ZMQ.SUB); + subscriber.connect("tcp://" + server); + subscriber.subscribe("Status".getBytes()); + while (!Thread.currentThread().isInterrupted()) { + String type = subscriber.recvStr(); + String contents = subscriber.recvStr(); + System.out.println(type + " : " + contents); + } + subscriber.close(); + context.term(); + } +} diff --git a/plugins/WagoPanel.form b/plugins/WagoPanel.form new file mode 100644 index 0000000..9864ffa --- /dev/null +++ b/plugins/WagoPanel.form @@ -0,0 +1,167 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="deviceStatePanel1" max="32767" attributes="0"/> + <Component id="panelSafety" max="32767" attributes="0"/> + <Component id="panelRobot1" max="32767" attributes="0"/> + <Component id="panelDewar" alignment="0" max="32767" attributes="0"/> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="panelSafety" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="panelDewar" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="panelRobot1" min="-2" max="-2" attributes="0"/> + <EmptySpace min="0" pref="0" max="-2" attributes="0"/> + <Component id="deviceStatePanel1" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="ch.psi.pshell.swing.DeviceStatePanel" name="deviceStatePanel1"> + <Properties> + <Property name="deviceName" type="java.lang.String" value="wago"/> + </Properties> + </Component> + <Container class="javax.swing.JPanel" name="panelSafety"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Safety"/> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="32767" attributes="0"/> + <Component id="buttonReleasePsys" linkSize="2" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="buttonReleaseLocal" linkSize="2" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="buttonReleaseLocal" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="buttonReleasePsys" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="buttonReleasePsys"> + <Properties> + <Property name="text" type="java.lang.String" value="Release PSYS"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonReleasePsysActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JButton" name="buttonReleaseLocal"> + <Properties> + <Property name="text" type="java.lang.String" value="Release Local"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonReleaseLocalActionPerformed"/> + </Events> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="panelRobot1"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder title="Dryer"/> + </Border> + </Property> + </Properties> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="32767" attributes="0"/> + <Component id="buttonHeater" linkSize="3" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Component id="buttonStream" linkSize="3" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="3" attributes="0"> + <Component id="buttonHeater" alignment="3" min="-2" max="-2" attributes="0"/> + <Component id="buttonStream" alignment="3" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JToggleButton" name="buttonHeater"> + <Properties> + <Property name="text" type="java.lang.String" value="Heater"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonHeaterActionPerformed"/> + </Events> + </Component> + <Component class="javax.swing.JToggleButton" name="buttonStream"> + <Properties> + <Property name="text" type="java.lang.String" value="Air Stream"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="buttonStreamActionPerformed"/> + </Events> + </Component> + </SubComponents> + </Container> + <Component class="ch.psi.pshell.swing.ProcessVariablePanel" name="panelDewar"> + <Properties> + <Property name="border" type="javax.swing.border.Border" editor="org.netbeans.modules.form.editors2.BorderEditor"> + <Border info="org.netbeans.modules.form.compat2.border.TitledBorderInfo"> + <TitledBorder justification="1" title="Dewar Light"/> + </Border> + </Property> + <Property name="deviceName" type="java.lang.String" value="led_level"/> + <Property name="showAdvanced" type="boolean" value="false"/> + <Property name="showButtons" type="boolean" value="false"/> + <Property name="showLimitButtons" type="boolean" value="false"/> + <Property name="showSlider" type="boolean" value="true"/> + <Property name="showStop" type="boolean" value="false"/> + </Properties> + </Component> + </SubComponents> +</Form> diff --git a/plugins/WagoPanel.java b/plugins/WagoPanel.java new file mode 100644 index 0000000..cacadcd --- /dev/null +++ b/plugins/WagoPanel.java @@ -0,0 +1,207 @@ +import ch.psi.mxsc.Controller; +import ch.psi.pshell.core.Context; +import ch.psi.pshell.swing.DevicePanel; +import java.util.concurrent.CompletableFuture; +import javax.swing.border.TitledBorder; + +/** + * + */ +public class WagoPanel extends DevicePanel { + + public WagoPanel() { + initComponents(); + this.startTimer(10000); + } + + + CompletableFuture future; + + @Override + public void onTimer(){ + if ((getDevice()!=null)){ + updateTitle(); + } + } + + void updateTitle(){ + Boolean roomTemp = (Controller.getInstance().isLedRoomTemp()); + if (roomTemp==null){ + ((TitledBorder)panelDewar.getBorder()).setTitle("Dewar Light"); + } else if (roomTemp==true){ + ((TitledBorder)panelDewar.getBorder()).setTitle("Dewar Light (room temperature)"); + } else { + ((TitledBorder)panelDewar.getBorder()).setTitle("Dewar Light (LN2)"); + } + } + + + void execute(String statement){ + try { + Context.getInstance().evalLineBackgroundAsync(statement).handle((ret, ex) -> { + if (WagoPanel.this.isShowing()){ + if (ex != null){ + showException((Exception)ex); + } + } + return ret; + }); + } catch (Exception ex) { + showException(ex); + } + } + + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + deviceStatePanel1 = new ch.psi.pshell.swing.DeviceStatePanel(); + panelSafety = new javax.swing.JPanel(); + buttonReleasePsys = new javax.swing.JButton(); + buttonReleaseLocal = new javax.swing.JButton(); + panelRobot1 = new javax.swing.JPanel(); + buttonHeater = new javax.swing.JToggleButton(); + buttonStream = new javax.swing.JToggleButton(); + panelDewar = new ch.psi.pshell.swing.ProcessVariablePanel(); + + deviceStatePanel1.setDeviceName("wago"); + + panelSafety.setBorder(javax.swing.BorderFactory.createTitledBorder("Safety")); + + buttonReleasePsys.setText("Release PSYS"); + buttonReleasePsys.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonReleasePsysActionPerformed(evt); + } + }); + + buttonReleaseLocal.setText("Release Local"); + buttonReleaseLocal.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonReleaseLocalActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelSafetyLayout = new javax.swing.GroupLayout(panelSafety); + panelSafety.setLayout(panelSafetyLayout); + panelSafetyLayout.setHorizontalGroup( + panelSafetyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelSafetyLayout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonReleasePsys) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonReleaseLocal) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + panelSafetyLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonReleaseLocal, buttonReleasePsys}); + + panelSafetyLayout.setVerticalGroup( + panelSafetyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelSafetyLayout.createSequentialGroup() + .addContainerGap() + .addGroup(panelSafetyLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonReleaseLocal) + .addComponent(buttonReleasePsys)) + .addContainerGap()) + ); + + panelRobot1.setBorder(javax.swing.BorderFactory.createTitledBorder("Dryer")); + + buttonHeater.setText("Heater"); + buttonHeater.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonHeaterActionPerformed(evt); + } + }); + + buttonStream.setText("Air Stream"); + buttonStream.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + buttonStreamActionPerformed(evt); + } + }); + + javax.swing.GroupLayout panelRobot1Layout = new javax.swing.GroupLayout(panelRobot1); + panelRobot1.setLayout(panelRobot1Layout); + panelRobot1Layout.setHorizontalGroup( + panelRobot1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelRobot1Layout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(buttonHeater) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addComponent(buttonStream) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + panelRobot1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {buttonHeater, buttonStream}); + + panelRobot1Layout.setVerticalGroup( + panelRobot1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(panelRobot1Layout.createSequentialGroup() + .addContainerGap() + .addGroup(panelRobot1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) + .addComponent(buttonHeater) + .addComponent(buttonStream)) + .addContainerGap()) + ); + + panelDewar.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Dewar Light", javax.swing.border.TitledBorder.LEFT, javax.swing.border.TitledBorder.DEFAULT_POSITION)); + panelDewar.setDeviceName("led_level"); + panelDewar.setShowAdvanced(false); + panelDewar.setShowButtons(false); + panelDewar.setShowLimitButtons(false); + panelDewar.setShowSlider(true); + panelDewar.setShowStop(false); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(deviceStatePanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelSafety, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelRobot1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(panelDewar, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(panelSafety, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(panelDewar, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(panelRobot1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(0, 0, 0) + .addComponent(deviceStatePanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + ); + }// </editor-fold>//GEN-END:initComponents + + private void buttonReleasePsysActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonReleasePsysActionPerformed + execute("release_psys()"); + }//GEN-LAST:event_buttonReleasePsysActionPerformed + + private void buttonReleaseLocalActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonReleaseLocalActionPerformed + execute("release_local()"); + }//GEN-LAST:event_buttonReleaseLocalActionPerformed + + private void buttonHeaterActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonHeaterActionPerformed + execute("set_heater(" + (buttonHeater.isSelected() ? "True": "False") + ")"); + }//GEN-LAST:event_buttonHeaterActionPerformed + + private void buttonStreamActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonStreamActionPerformed + execute("set_air_stream(" + (buttonStream.isSelected()? "True": "False")+ ")"); + }//GEN-LAST:event_buttonStreamActionPerformed + + + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JToggleButton buttonHeater; + private javax.swing.JButton buttonReleaseLocal; + private javax.swing.JButton buttonReleasePsys; + private javax.swing.JToggleButton buttonStream; + private ch.psi.pshell.swing.DeviceStatePanel deviceStatePanel1; + private ch.psi.pshell.swing.ProcessVariablePanel panelDewar; + private javax.swing.JPanel panelRobot1; + private javax.swing.JPanel panelSafety; + // End of variables declaration//GEN-END:variables +} diff --git a/plugins/gui.form b/plugins/gui.form new file mode 100644 index 0000000..5775937 --- /dev/null +++ b/plugins/gui.form @@ -0,0 +1,62 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo"> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="32767" attributes="0"/> + <Component id="renderer1" min="-2" pref="154" max="-2" attributes="0"/> + <EmptySpace min="-2" pref="82" max="-2" attributes="0"/> + </Group> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace min="-2" pref="51" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jButton1" min="-2" max="-2" attributes="0"/> + <Component id="linePlotJFree1" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace pref="250" max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace min="-2" pref="24" max="-2" attributes="0"/> + <Component id="jButton1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="renderer1" min="-2" pref="102" max="-2" attributes="0"/> + <EmptySpace pref="20" max="32767" attributes="0"/> + <Component id="linePlotJFree1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="jButton1"> + <Properties> + <Property name="text" type="java.lang.String" value="Abort"/> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/> + </Events> + </Component> + <Component class="ch.psi.pshell.imaging.Renderer" name="renderer1"> + </Component> + <Component class="ch.psi.pshell.plot.LinePlotJFree" name="linePlotJFree1"> + </Component> + </SubComponents> +</Form> diff --git a/plugins/gui.java b/plugins/gui.java new file mode 100644 index 0000000..abeb59b --- /dev/null +++ b/plugins/gui.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2014 Paul Scherrer Institute. All rights reserved. + */ + +import ch.psi.pshell.ui.Panel; +import ch.psi.utils.State; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * + */ +public class gui extends Panel { + + public gui() { + initComponents(); + } + + //Overridable callbacks + @Override + public void onInitialize(int runCount) { + + } + + @Override + public void onStateChange(State state, State former) { + + } + + @Override + public void onExecutedFile(String fileName, Object result) { + } + + + //Callback to perform update - in event thread + @Override + protected void doUpdate() { + } + + @SuppressWarnings("unchecked") + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jButton1 = new javax.swing.JButton(); + renderer1 = new ch.psi.pshell.imaging.Renderer(); + linePlotJFree1 = new ch.psi.pshell.plot.LinePlotJFree(); + + jButton1.setText("Abort"); + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(renderer1, javax.swing.GroupLayout.PREFERRED_SIZE, 154, javax.swing.GroupLayout.PREFERRED_SIZE) + .addGap(82, 82, 82)) + .addGroup(layout.createSequentialGroup() + .addGap(51, 51, 51) + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jButton1) + .addComponent(linePlotJFree1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)) + .addContainerGap(250, Short.MAX_VALUE)) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addGap(24, 24, 24) + .addComponent(jButton1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(renderer1, javax.swing.GroupLayout.PREFERRED_SIZE, 102, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 20, Short.MAX_VALUE) + .addComponent(linePlotJFree1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + }// </editor-fold>//GEN-END:initComponents + + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + try { + abort(); + } catch (InterruptedException ex) { + Logger.getLogger(gui.class.getName()).log(Level.SEVERE, null, ex); + } + }//GEN-LAST:event_jButton1ActionPerformed + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private ch.psi.pshell.plot.LinePlotJFree linePlotJFree1; + private ch.psi.pshell.imaging.Renderer renderer1; + // End of variables declaration//GEN-END:variables +} diff --git a/script/LN2_Monitoring.scd b/script/LN2_Monitoring.scd new file mode 100644 index 0000000..d2ab014 --- /dev/null +++ b/script/LN2_Monitoring.scd @@ -0,0 +1,15 @@ +[ + [ [ true, "phase_separator_level", "Device", 1, 1, "102,204,255" ], + [ true, "filling_phase_separator", "Device", 1, 1, "51,255,255" ], + [ true, "filling_dewar", "Device", 1, 1, "0,0,102" ], + [ true, "dewar_level", "Device", 1, 1, "0,51,153" ], + [ true, "rim_heater_temp", "Device", 1, 1, "255,0,51" ] ], + [ [ "1", 0.0, 100.0, null, null, 1000000.0, false, null ], + [ "2", null, null, null, null, null, null, null ], + [ "3", null, null, null, null, null, null, null ], + [ "4", null, null, null, null, null, null, null ], + [ "5", null, null, null, null, null, null, null ] ], + [ [ ] ], + [ [ "", 20000, 100 ], + [ "", "" ] ] +] \ No newline at end of file diff --git a/script/LevelMonitoring.scd b/script/LevelMonitoring.scd new file mode 100644 index 0000000..ae328cc --- /dev/null +++ b/script/LevelMonitoring.scd @@ -0,0 +1,12 @@ +[ + [ [ true, "phase_separator_level", "Device", 1, 1, "255,0,0" ], + [ true, "dewar_level", "Device", 1, 1, "0,0,255" ] ], + [ [ "1", 0.0, 100.0, null, null, 100000.0, false, null ], + [ "2", null, null, null, null, null, null, null ], + [ "3", null, null, null, null, null, null, null ], + [ "4", null, null, null, null, null, null, null ], + [ "5", null, null, null, null, null, null, null ] ], + [ [ ] ], + [ [ "", 20000, 100 ], + [ "", "" ] ] +] \ No newline at end of file diff --git a/script/calibration/BinarySearchYZ.py b/script/calibration/BinarySearchYZ.py new file mode 100644 index 0000000..42db379 --- /dev/null +++ b/script/calibration/BinarySearchYZ.py @@ -0,0 +1,29 @@ +import plotutils +import math + + +#STRATEGY = "Normal" +#STRATEGY = "Boundary" +#STRATEGY = "FullNeighborhood" +RANGE = [-5.0, 5.0] +STEP_SIZE = 0.1 +LATENCY = 0.05 + + +robot.enable() +move_to_laser() + + +robot.set_motors_enabled(True) +current_y = robot_y.getPosition() +current_z = robot_z.getPosition() + + +r = bsearch([robot_y, robot_z], laser_distance,[RANGE[0], RANGE[0]], [RANGE[1], RANGE[1]], [STEP_SIZE,STEP_SIZE], relative = True, maximum=True, strategy = STRATEGY, latency = LATENCY, title = "Binary Search YZ") + + +print r.print() +opt_y, opt_z= r.getOptimalPosition() +offset_y, offset_z = opt_y - current_y, opt_z - current_z + +print "offset_y: ", offset_y, " offset_z: ", offset_z \ No newline at end of file diff --git a/script/calibration/HillClimbingXZ.py b/script/calibration/HillClimbingXZ.py new file mode 100644 index 0000000..2fcab26 --- /dev/null +++ b/script/calibration/HillClimbingXZ.py @@ -0,0 +1,45 @@ +import plotutils +import math + + +#STRATEGY = "Normal" +STRATEGY = "Boundary" +#STRATEGY = "FullNeighborhood" +RANGE = [-5.0, 5.0] +INITIAL_STEP = 1.0 +STEP_SIZE = 0.05 +LATENCY = 0.05 +NOISE_FILTER = 1 + + +robot.enable() +move_to_laser() + + +robot.set_motors_enabled(True) + +current_x = robot_x.getPosition() +current_z = robot_z.getPosition() + + + + +class Distance(Readable): + def read(self): + ret = ue.readable.read() + ret = 0.0 if math.isnan(ret) else ret + return ret + +laser_distance=Distance() +start = time.time() +r = hsearch([robot_x, robot_z],laser_distance, [RANGE[0], RANGE[0]], [RANGE[1], RANGE[1]], [INITIAL_STEP,INITIAL_STEP], [STEP_SIZE,STEP_SIZE], NOISE_FILTER, relative = True, maximum=True, latency = LATENCY, title = "Hill Climbing XZ") + + + +print r.print() +opt_x, opt_z= r.getOptimalPosition() +offset_x, offset_z = opt_x - current_x, opt_z - current_z + +print "offset_x: ", offset_x, " offset_z: ", offset_z + + diff --git a/script/calibration/ScanRZ.py b/script/calibration/ScanRZ.py new file mode 100644 index 0000000..55d3bba --- /dev/null +++ b/script/calibration/ScanRZ.py @@ -0,0 +1,31 @@ +#Imports +import plotutils +from mathutils import fit_gaussian, Gaussian + +#Parameters +RANGE = [-120.0,120.0] +STEP = 5.0 +LATENCY = 0.005 +RELATIVE = False + +#Enabling and checking +#enable_motion() +#system_check() +robot.enable() + + +#Body +robot.set_tool(TOOL_DEFAULT) +move_to_laser() +#robot.set_joint_motors_enabled(True) +robot.set_motors_enabled(True) +robot_rz.move(0.0) +robot.set_motors_enabled(True) +ret = lscan(robot_rz, ue.readable, RANGE[0], RANGE[1], STEP, latency = LATENCY, relative = RELATIVE, range = "auto", title = "Scan2") + + +#Cleanup + + + + diff --git a/script/calibration/ScanX.py b/script/calibration/ScanX.py new file mode 100644 index 0000000..e72350d --- /dev/null +++ b/script/calibration/ScanX.py @@ -0,0 +1,81 @@ +import plotutils +from mathutils import fit_gaussian, Gaussian + + +d = robot.get_distance_to_pnt("pLaser") +if d<0: + raise Exception ("Error calculating distance to laser: " + str(d)) + +if d>20: + raise Exception ("Should be near the laser position to perform the scan") + +RANGE = [-2.0, 2.0] #[-1.5, 1.5] +STEP = 0.02 +Z_OFFSET = 0 #-1.0 +LATENCY = 0.025 +BORDER_SIZE = 0.15 + +robot.enable() +robot.set_motors_enabled(True) +current_positon = robot_x.getPosition() +robot_z.moveRel(Z_OFFSET) + +robot.setPolling(25) +try: + ret = lscan(robot_x, ue.readable, RANGE[0], RANGE[1], STEP, latency = LATENCY, relative = True) +finally: + robot.setPolling(DEFAULT_ROBOT_POLLING) + +d = ret.getReadable(0) + +first_index = -1 +last_index = -1 +for i in range(len(d)): + if not math.isnan(d[i]): + if first_index<0: + first_index = i + last_index = i + +if first_index == -1 or last_index < first_index: + raise Exception("Invalid range") + + +remove = int(max(BORDER_SIZE, STEP) / STEP) + +_range = [first_index+remove, last_index-remove] +if _range[1] <= _range[0]: + raise Exception("Invalid range: " + str(_range)) + + +center_index = int((_range[0] + _range[1])/2) +center_positon = ret.getPositions(0)[center_index] + + + + +y = ret.getReadable(0)[_range[0] : _range[1]] +x = ret.getPositions(0)[_range[0]: _range[1]] +#x = enforce_monotonic(x) +#(normalization, mean_val, sigma) = fit_gaussian([-v for v in y], x) + + +closest_x = x[y.indexOf(min(y))] +closest_y = y[y.indexOf(min(y))] + + + +if closest_x is None or closest_x <= ret.getPositions(0)[first_index] or closest_x >= ret.getPositions(0)[last_index]: + raise Exception("Invalid Fit") + + + +center_offset = center_positon-closest_y +#center_offset = current_positon-closest_y + + + +p=get_plots()[0] +p.addMarker(closest_y, p.AxisId.X, str(closest_y), Color.GREEN) + +robot.set_motors_enabled(True) +robot_x.move(closest_x) diff --git a/script/calibration/ScanY.py b/script/calibration/ScanY.py new file mode 100644 index 0000000..17252f1 --- /dev/null +++ b/script/calibration/ScanY.py @@ -0,0 +1,81 @@ +import plotutils +from mathutils import fit_gaussian, Gaussian + + +d = robot.get_distance_to_pnt("pLaser") +if d<0: + raise Exception ("Error calculating distance to laser: " + str(d)) + +if d>20: + raise Exception ("Should be near the laser position to perform the scan") + +RANGE = [-2.0, 2.0] #[-1.5, 1.5] +STEP = 0.02 +Z_OFFSET = 0 #-1.0 +LATENCY = 0.025 +BORDER_SIZE = 0.15 + +robot.enable() +robot.set_motors_enabled(True) +current_positon = robot_y.getPosition() +robot_z.moveRel(Z_OFFSET) + +robot.setPolling(25) +try: + ret = lscan(robot_y, ue.readable, RANGE[0], RANGE[1], STEP, latency = LATENCY, relative = True) +finally: + robot.setPolling(DEFAULT_ROBOT_POLLING) + +d = ret.getReadable(0) + +first_index = -1 +last_index = -1 +for i in range(len(d)): + if not math.isnan(d[i]): + if first_index<0: + first_index = i + last_index = i + +if first_index == -1 or last_index < first_index: + raise Exception("Invalid range") + + +remove = int(max(BORDER_SIZE, STEP) / STEP) + +_range = [first_index+remove, last_index-remove] +if _range[1] <= _range[0]: + raise Exception("Invalid range: " + str(_range)) + + +center_index = int((_range[0] + _range[1])/2) +center_positon = ret.getPositions(0)[center_index] + + + + +y = ret.getReadable(0)[_range[0] : _range[1]] +x = ret.getPositions(0)[_range[0]: _range[1]] +#x = enforce_monotonic(x) +#(normalization, mean_val, sigma) = fit_gaussian([-v for v in y], x) + + +closest_y = x[y.indexOf(min(y))] +closest_x = y[y.indexOf(min(y))] + + + +if closest_y is None or closest_y <= ret.getPositions(0)[first_index] or closest_y >= ret.getPositions(0)[last_index]: + raise Exception("Invalid Fit") + + + +center_offset = center_positon-closest_y +#center_offset = current_positon-closest_y + + + +p=get_plots()[0] +p.addMarker(closest_y, p.AxisId.X, str(closest_y), Color.GREEN) + +robot.set_motors_enabled(True) +robot_y.move(closest_y) diff --git a/script/calibration/ScanYZ.py b/script/calibration/ScanYZ.py new file mode 100644 index 0000000..bee63e6 --- /dev/null +++ b/script/calibration/ScanYZ.py @@ -0,0 +1,93 @@ +import plotutils +from mathutils import fit_gaussian, Gaussian + +SINGLE_PASS = False +if SINGLE_PASS: + STEP_SIZE = 0.2 +else: + STEP_SIZE = 1.0 +STEP_Z_FINAL = 0.1 + +RANGE = [-5.0, 5.0] +LATENCY = 0.05 + +Z_FINAL_OFFSET = 0.0 + + +SINGLE_PASS = True +STEP_SIZE = 0.1 + + +robot.enable() +move_to_laser() + +step_y = STEP_SIZE +step_z = STEP_SIZE +range_y = [RANGE[0], RANGE[1]] +range_z = [RANGE[0], RANGE[1]] + +robot.set_motors_enabled(True) +current_y = robot_y.getPosition() +current_z = robot_z.getPosition() + +print "Current pos y,z" , current_y, ",", current_z +ret = ascan([robot_y, robot_z], ue.readable, [range_y[0], range_z[0]], [range_y[1], range_z[1]], [step_y,step_z], latency = LATENCY, relative = True , zigzag=False, title = "Scan XY") +data = ret.getData(0)[0] +#plot(Convert.transpose(data), title="Data") + +integ = [] +for x in data: integ.append(sum( [ (0.0 if (math.isnan(y)) else y) for y in x])) + +xdata= frange(range_y[0], range_y[1], step_y , False, True) +p = plot(integ, title = "Fit", xdata=xdata)[0] + + +max_x_index = integ.index(max(integ)) +max_x = xdata[max_x_index] +try: + (normalization, mean_val, sigma) = fit_gaussian(integ, xdata) +except: + raise Exception("Invalid Fit") +gaussian = Gaussian(normalization, mean_val, sigma) +xdata= frange(range_y[0], range_y[1], step_y/100.0 , False, True) +plot_function(p, gaussian, "Fit", xdata, show_points = False, show_lines = True, color = Color.BLUE) + +#So +if abs(mean_val - max_x) > 1.0: + raise Exception("Invalid Y detection") +y_offset = mean_val +center_y = current_y + y_offset + +print "Y offset = ", y_offset + +robot_y.move(center_y) +if SINGLE_PASS: + z_scan_data = data[max_x_index] +else: + step_z = STEP_Z_FINAL + ret2 = lscan(robot_z, ue.readable, range_z[0], range_z[1], step_z, latency = LATENCY, relative = True , zigzag=False) + z_scan_data = ret2.getData(0)[0] + +max_z_index= z_scan_data.index(max(z_scan_data)) +last_z_index = 0 +for i in range(len(z_scan_data)): + if not math.isnan(z_scan_data[i]): + last_z_index = i +#Shape is cone: z is inceraseing. For proper detection last Z must be furthest +if abs(max_z_index - last_z_index) * step_z > 1.0: + raise Exception("Invalid Z detection") + +if SINGLE_PASS: + max_z = ret.getPositions(1)[len(data[0]) * max_x_index + last_z_index] +else: + max_z = ret2.getPositions(0)[last_z_index] + +z_offset = max_z - current_z + Z_FINAL_OFFSET + +robot_z.move(max_z + Z_FINAL_OFFSET) + +print "Z offset = ", z_offset + + +#Updating tool: +#update_tool(None, x_offset=x_offset, z_offset=z_offset) diff --git a/script/calibration/ToolCalibration.py b/script/calibration/ToolCalibration.py new file mode 100644 index 0000000..602403b --- /dev/null +++ b/script/calibration/ToolCalibration.py @@ -0,0 +1,60 @@ +import plotutils +from mathutils import fit_gaussian, Gaussian + + +robot.assert_tool(TOOL_CALIBRATION) +robot.set_motors_enabled(True) +robot.set_joint_motors_enabled(True) + + +initial_pos = robot.get_cartesian_pos() + +robot.enable() +move_to_laser() + +robot.align() + + +run("calibration/ScanYZ") + +robot.set_motors_enabled(True) + + +first_y = robot_y.take() +first_z = robot_z.take() +first_y = ue.take() +first_j6 = robot_j6.take() +if first_y is None: + raise Exception("Invalid YZ scan values in first scan") + + +robot.set_joint_motors_enabled(True) +if first_j6>0: + robot_j6.moveRel(-180.0, -1) +else: + robot_j6.moveRel(180.0, -1) + + +robot.set_motors_enabled(True) +run("calibration/ScanYZ") + +robot.set_motors_enabled(True) + +second_y = robot_y.take() +second_z = robot_z.take() +second_y = ue.take() +second_j6 = robot_j6.take() +if second_y is None: + raise Exception("Invalid XZ scan values in first scan") + + +#Updates the tool +xoff = (first_x - second_x)/2 +yoff = (first_y - second_y)/2 +t=robot.get_tool_trsf(TOOL_DEFAULT) +t[0]=xoff +t[1]=-yoff +robot.set_tool_trsf(t, TOOL_DEFAULT) + + + diff --git a/script/calibration/ToolCalibration2.py b/script/calibration/ToolCalibration2.py new file mode 100644 index 0000000..e9b71ae --- /dev/null +++ b/script/calibration/ToolCalibration2.py @@ -0,0 +1,86 @@ +import plotutils +from mathutils import fit_gaussian, Gaussian + + +#robot.assert_tool(TOOL_CALIBRATION) +#cal_tool = TOOL_DEFAULT +cal_tool = TOOL_CALIBRATION + +robot.set_tool(cal_tool) +robot.enable() +move_to_laser() + + +robot.set_motors_enabled(True) +robot.set_joint_motors_enabled(True) +initial_pos = robot.get_cartesian_pos() + +robot.enable() +move_to_laser() + +#robot.align() + + +run("calibration/ScanY") + +pos1 = robot.get_cartesian_pos() +x1, y1 = closest_x, closest_y + +print "Closest 1: ", [x1, y1] +print "Position 1: ", pos1 + + +pj6 = robot_j6.position +if pj6>0: + robot_j6.move(pj6 - 180.0) +else: + robot_j6.move(pj6 + 180.0) + + +run("calibration/ScanY") + + +x2, y2 = closest_x, closest_y + +print "Closest 2: ", [x2, y2] + + + +off_x = x1 - x2 + +#robot.set_motors_enabled(True) +#robot_x.moveRel(off_x, -1) + +#For composing cannot use tcp_p, need another auxiliary point. tcp_t is also destroyed. +robot.set_pnt(robot.get_cartesian_pos(), "pTemp") +robot.set_trsf([off_x, 0,0,0,0,0]) +c=robot.compose("pTemp", FRAME_TABLE, "tcp_t" ) +robot.set_pnt(c, "pTemp") +robot.movel("pTemp", cal_tool, DESC_SCAN, sync=True) + + +pos2 = robot.get_cartesian_pos() +print pos2 + +print "Position 2: ", pos2 + + + +#Updates the tool +xoff = (pos2[0]-pos1[0])/2 +yoff = (pos2[1]-pos1[1])/2 + +#print "Offset: ", [xoff, yoff] + +t=robot.get_tool_trsf(TOOL_DEFAULT) +t[0]=xoff +t[1]=-yoff +print "Offset: ", [t[0], t[1]] +robot.set_tool_trsf(t, TOOL_DEFAULT) + +robot.set_tool(TOOL_DEFAULT) +d = robot.get_distance_to_pnt("pLaser") +if d<POSITION_TOLERANCE: + print "Moving calibrated tool to laser" +else: + print "Cannot move calibrated tool to laser: toog big offset" diff --git a/script/calibration/ToolCalibration3.py b/script/calibration/ToolCalibration3.py new file mode 100644 index 0000000..969707d --- /dev/null +++ b/script/calibration/ToolCalibration3.py @@ -0,0 +1,83 @@ +import plotutils +from mathutils import fit_gaussian, Gaussian + +cal_tool = TOOL_CALIBRATION + +robot.set_tool(cal_tool) + +robot.enable() +move_to_laser() + + +robot.set_motors_enabled(True) +robot.set_joint_motors_enabled(True) +initial_pos = robot.get_cartesian_pos() + +#robot.align() +try: + robot.set_frame(FRAME_TABLE) + run("calibration/ScanX") +finally: + robot.set_default_frame() + +pos1 = robot.get_cartesian_pos() +x1, l1 = closest_x, closest_y + +print "Scan 1 result: ", [x1, l1] +print "Position 1: ", pos1 + + +pj6 = robot_j6.position +if pj6>0: + robot_j6.move(pj6 - 180.0) +else: + robot_j6.move(pj6 + 180.0) + + +try: + robot.set_frame(FRAME_TABLE) + run("calibration/ScanX") +finally: + robot.set_default_frame() + +pos2 =robot.get_cartesian_pos() +x2, l2 = closest_x, closest_y + +print "Scan 2 result: ", [x2, l2] +print "Position 2: ", pos1 + +off_l = l2 - l1 +print "Offset l: ", off_l + +#For composing cannot use tcp_p, need another auxiliary point. tcp_t is also destroyed. +robot.set_pnt(robot.get_cartesian_pos(), "pTemp") +robot.set_trsf([0, -off_l, 0, 0, 0, 0]) +c=robot.compose("pTemp", FRAME_TABLE, "tcp_t" ) +robot.set_pnt(c, "pTemp") +robot.movel("pTemp", cal_tool, DESC_SCAN, sync=True) + + +pos3 = robot.get_cartesian_pos() +print "Position 3: ", pos3 + + +#Updates the tool +t=robot.get_tool_trsf(TOOL_DEFAULT) +print "Former tool: " + str(t) + +xoff = (pos3[0]-pos1[0])/2 +yoff = (pos3[1]-pos1[1])/2 +xrot = math.degrees(math.atan(yoff/t[2])) +yrot = math.degrees(math.atan(xoff/t[2])) +t[0]=xoff +t[1]=-yoff +print "Calibrated tool: " + str(t) +robot.set_tool_trsf(t, TOOL_DEFAULT) + +robot.set_tool(TOOL_DEFAULT) +d = robot.get_distance_to_pnt("pLaser") +if d<POSITION_TOLERANCE: + print "Moving calibrated tool to laser" + #move_to_laser() +else: + print "Cannot move calibrated tool to laser: too big offset" diff --git a/script/client/PShellClient.py b/script/client/PShellClient.py new file mode 100644 index 0000000..a40b1df --- /dev/null +++ b/script/client/PShellClient.py @@ -0,0 +1,369 @@ +import threading +import time +import sys +import requests +import json + +try: + from urllib import quote # Python 2 +except ImportError: + from urllib.parse import quote # Python 3 + +try: + from sseclient import SSEClient +except: + SSEClient = None + + +class PShellClient: + def __init__(self, url): + self.url = url + self.sse_event_loop_thread = None + self.subscribed_events = None + self.event_callback = None + + def _get_response(self, response, is_json=True): + if response.status_code != 200: + raise Exception(response.text) + return json.loads(response.text) if is_json else response.text + + def _get_binary_response(self, response): + if response.status_code != 200: + raise Exception(response.text) + return response.raw.read() + + def get_version(self): + """Return application version. + + Args: + + Returns: + String with application version. + + """ + return self._get_response(requests.get(url=self.url+"/version"), False) + + def get_config(self): + """Return application configuration. + + Args: + + Returns: + Dictionary. + """ + return self._get_response(requests.get(url=self.url+"/config")) + + def get_state(self): + """Return application state. + + Args: + + Returns: + String: Invalid, Initializing,Ready, Paused, Busy, Disabled, Closing, Fault, Offline + """ + return self._get_response(requests.get(url=self.url+"/state")) + + def get_logs(self): + """Return application logs. + + Args: + + Returns: + List of logs. + Format of each log: [date, time, origin, level, description] + + """ + return self._get_response(requests.get(url=self.url+"/logs")) + + def get_history(self, index): + """Access console command history. + + Args: + index(int): Index of history entry (0 is the most recent) + + Returns: + History entry + + """ + return self._get_response(requests.get(url=self.url+"/history/"+str(index)), False) + + def get_script(self, path): + """Return script. + + Args: + path(str): Script path (absolute or relative to script folder) + + Returns: + String with file contents. + + """ + return self._get_response(requests.get(url=self.url+"/script/"+str(path)), False) + + def get_devices(self): + """Return global devices. + + Args: + + Returns: + List of devices. + Format of each device record: [name, type, state, value, age] + + """ + return self._get_response(requests.get(url=self.url+"/devices")) + + def abort(self, command_id=None): + """Abort execution of command + + Args: + command_id(optional, int): id of the command to be aborted. + if None (default), aborts the foreground execution. + + Returns: + + """ + if command_id is None: + requests.get(url=self.url+"/abort") + else: + return requests.get(url=self.url+"/abort/"+str(command_id)) + + def reinit(self): + """Reinitialize the software. + + Args: + + Returns: + + """ + requests.get(url=self.url+"/reinit") + + def stop(self): + """Stop all devices implementing the 'Stoppable' interface. + + Args: + + Returns: + + """ + requests.get(url=self.url+"/stop") + + def update(self): + """Update all global devices. + + Args: + + Returns: + + """ + requests.get(url=self.url+"/update") + + def eval(self,statement): + """Evaluates a statement in the interpreter. + If the statement finishes by '&', it is executed in background. + Otherwise statement is executed in foreground (exclusive). + + Args: + statement(str): input statement + + Returns: + String containing the console return. + If an exception is produces in the interpretor, it is re-thrown here. + """ + statement = quote(statement) + return self._get_response(requests.get(url=self.url+"/eval/"+statement), False) + + def run(self,script, pars=None, background=False): + """Executes script in the interpreter. + + Args: + script(str): name of the script (absolute or relative to the script base folder). Extension may be omitted. + pars(optional, list or dict): if a list is given, it sets sys.argv for the script. + If a dict is given, it sets global variable for the script. + background(optional, bool): if True script is executed in background. + + Returns: + Return value of the script. + If an exception is produces in the interpretor, it is re-thrown here. + """ + return self._get_response(requests.put(url=self.url+"/run", json={"script":script, "pars":pars, "background":background, "async":False })) + + def start_eval(self,statement): + """Starts evaluation of a statement in the interpreter. + If the statement finishes by '&', it is executed in background. + Otherwise statement is executed in foreground (exclusive). + + Args: + statement(str): input statement + + Returns: + Command id (int), which is used to retrieve command execution status/result (get_result). + """ + statement = quote(statement) + return int(self._get_response(requests.get(url=self.url+"/evalAsync/"+statement), False)) + + def start_run(self,script, pars=None, background=False): + """Starts execution of a script in the interpreter. + + Args: + script(str): name of the script (absolute or relative to the script base folder). Extension may be omitted. + pars(optional, list or dict): if a list is given, it sets sys.argv for the script. + If a dict is given, it sets global variable for the script. + background(optional, bool): if True script is executed in background. + + Returns: + Command id (int), which is used to retrieve command execution status/result (get_result). + """ + return int(self._get_response(requests.put(url=self.url+"/run", json={"script":script, "pars":pars, "background":background, "async":True }))) + + def get_result(self, command_id=-1): + """Gets status/result of a command executed asynchronously (start_eval and start_run). + + Args: + command_id(optional, int): command id. If equals to -1 (default) return status/result of the foreground task. + + Returns: + Dictionary with the fields: 'id' (int): command id + 'status' (str): unlaunched, invalid, removed, running, aborted, failed or completed. + 'exception' (str): if status equals 'failed', holds exception string. + 'return' (obj): if status equals 'completed', holds return value of script (start_run) + or console return (start_eval) + """ + return self._get_response(requests.get(url=self.url+"/result/"+str(command_id))) + + def help(self, input = "<builtins>"): + """Returns help or auto-completion strings. + + Args: + input(optional, str): - ":" for control commands + - "<builtins>" for builtin functions + - "devices" for device names + - builtin function name for function help + - else contains entry for auto-completion + + Returns: + List + + """ + return self._get_response(requests.get(url=self.url+"/autocompletion/" + input)) + + def get_contents(self, path=None): + """Returns contents of data path. + + Args: + path(optional, str): Path to data relative to data home path. + - Folder + - File + - File (data root) | internal path + - internal path (on currently open data root) + + Returns: + List of contents + + """ + return self._get_response(requests.get(url=self.url+ "/contents" + ("" if path is None else ( "/"+path))), False) + + def get_data(self, path, type="txt"): + """Returns data on a given path. + + Args: + path(str): Path to data relative to data home path. + - File (data root) | internal path + - internal path (on currently open data root) + type(optional, str): txt, "json", "bin", "bs" + + Returns: + Data accordind to selected format/. + + """ + if type == "json": + return self._get_response(requests.get(url=self.url+ "/data-json/"+path), True) + elif type == "bin": + return self._get_binary_response(requests.get(url=self.url+"/data-bin/"+path, stream=True)) + elif type == "bs": + from collections import OrderedDict + bs = self._get_binary_response(requests.get(url=self.url+"/data-bs/"+path, stream=True)) + index=0 + msg = [] + for i in range(4): + size =int.from_bytes(bs[index:index+4], byteorder='big', signed=False) + index=index+4 + msg.append(bs[index:index+size]) + index=index+size + [main_header, data_header, data, timestamp] = msg + main_header = json.loads(main_header, object_pairs_hook=OrderedDict) + data_header = json.loads(data_header, object_pairs_hook=OrderedDict) + channel = data_header["channels"][0] + channel["encoding"] = "<" if channel.get("encoding", "little") else ">" + from bsread.data.helpers import get_channel_reader + channel_value_reader = get_channel_reader(channel) + return channel_value_reader(data) + + return self._get_response(requests.get(url=self.url+ "/data" + ("" if path is None else ( "/"+path))), False) + + def print_logs(self): + for l in self.get_logs(): + print ("%s %s %-20s %-8s %s" % tuple(l)) + + def print_devices(self): + for l in self.get_devices(): + print ("%-16s %-32s %-10s %-32s %s" % tuple(l)) + + def print_help(self, input = "<builtins>"): + for l in self.help(input): + print (l) + + #Events + def _sse_event_loop_task(self): + try: + while True: + try: + messages = SSEClient(self.url+"/events") + for msg in messages: + if (self.subscribed_events is None) or (msg.event in self.subscribed_events): + try: + value = json.loads(msg.data) + except: + value = str(msg.data) + self.event_callback(msg.event, value) + except IOError as e: + #print(e) + pass + except: + print("Error:", sys.exc_info()[1]) + #raise + finally: + print ("Exit SSE loop task") + self.sse_event_loop_thread = None + + + def start_sse_event_loop_task(self, subscribed_events = None, event_callback = None): + """ + Initializes server event loop task. + Args: + subscribed_events: list of event names to substribe to. If None subscribes to all. + event_callback: callback function. If None, self.on_event is called instead. + + Usage example: + def on_event(name, value): + if name == "state": + print ("State changed: ", value) + elif name == "record": + print ("Received scan record: ", value) + + pc.start_sse_event_loop_task(["state", "record"], on_event) + + """ + self.event_callback = event_callback if event_callback is not None else self.on_event + self.subscribed_events = subscribed_events + if SSEClient is not None: + if self.sse_event_loop_thread is None: + self.sse_event_loop_thread = threading.Thread(target=self._sse_event_loop_task, \ + args = (), \ + kwargs={}, \ + daemon=True) + self.sse_event_loop_thread.start() + else: + raise Exception ("sseclient library is not instlled: server events are not available") + + def on_event(self, name, value): + pass + \ No newline at end of file diff --git a/script/client/TellClient.py b/script/client/TellClient.py new file mode 100644 index 0000000..256dbdd --- /dev/null +++ b/script/client/TellClient.py @@ -0,0 +1,184 @@ +from PShellClient import PShellClient +import json +import time +import sys + + + +class TellClient(PShellClient): + def __init__(self, url): + PShellClient.__init__(self, url) + self.start_sse_event_loop_task(["state", "shell"]) + self.state = self.get_state() + self.debug=False + + def on_event(self, name, value): + if name == "state": + self.state = value + print ("State: ", value) + elif name == "shell": + if self.debug: + print ("> ", value) + + def get_state(self): + self.state = PShellClient.get_state(self) + return self.state + + def wait_ready(self): + count = 0 + #Monitors event but polls every second just n case an event is missed + while (True): + if self.state != "Busy": + break + time.sleep(0.01) + count = count + 1 + if count>=100: + count=0 + self.get_state() + if self.state != "Ready": + raise Exception("Invalid state: " + str(self.state)) + + def set_in_mount_position(self, value): + self.eval("in_mount_position = " + str(value) +"&") + + def is_in_mount_position(self): + return self.eval("in_mount_position&").lower()=="true" + + def get_samples_info(self): + return json.loads(self.eval("get_samples_info()&")) + + def set_samples_info(self, info): + #c.run("data/set_samples_info", pars= [info,], background=True) + self.eval("set_samples_info(" + json.dumps(info) + ")&") + + def start_cmd(self, cmd, *argv): + cmd = cmd + "(" + for a in argv: + cmd = cmd + (("'" + a + "'") if type(a) is str else str(a) ) + ", " + cmd = cmd + ")" + ret = self.start_eval(cmd) + self.get_state() + return ret + + def wait_cmd(self, cmd): + self.wait_ready() + result = self.get_result(cmd) + #print (result) + if result["exception"] is not None: + raise Exception(result["exception"] ) + return result["return"] + + def mount(self, segment, puck, sample, force=False, read_dm=False, auto_unmount=False): + #return self.run("motion/mount", pars= [segment,puck, sample, force, read_dm], background=True) + return self.start_cmd("mount", segment, puck, sample, force, read_dm, auto_unmount) + + def unmount(self, segment = None, puck = None, sample = None, force=False): + return self.start_cmd("unmount", segment, puck, sample, force) + + def scan_pin(self, segment, puck, sample, force=False): + return self.start_cmd("scan_pin", segment, puck, sample, force) + + def scan_puck(self, segment, puck, force=False): + return self.start_cmd("scan_puck", segment, puck, force) + + def dry(self, heat_time=30.0, speed=0.5, wait_cold = 30.0): + return self.start_cmd("dry", heat_time, speed, wait_cold) + + def move_cold(self): + return self.start_cmd("move_cold") + + def trash(self): + return self.start_cmd("trash") + + def abort_cmd(self): + self.abort() + self.eval("robot.stop_task()&") + + def set_gonio_mount_position(homing = False): + if homing: + self.eval("home_fast_table()") + self.eval("set_mount_position()") + + def get_mounted_sample(self): + ret = self.eval("get_setting('mounted_sample_position')&").strip() + return None if len(ret)==0 else ret + + def get_system_check(self): + try: + ret = self.eval("system_check()&") + except Exception as ex: + return ex + return "Ok" + + def get_robot_state(self): + return self.eval("robot.state&") + + + def get_robot_status(self): + status = self.eval("robot.take()&") + return status + + def get_detected_pucks(self): + return self.eval("get_detected_pucks()&") + + def set_pin_offset(self, value): + self.eval("set_pin_offset(" + str(value)+ ")&") + + def get_pin_offset(self): + return self.eval("get_pin_offset()&") + + def print_info(self): + print ("State: " + str(self.get_state())) + print ("Mounted sample: " + str(self.get_mounted_sample())) + print ("System check: " + str(self.get_system_check())) + print ("Robot state: " + str(self.get_robot_state())) + print ("Robot status: " + str(self.get_robot_status())) + print ("Detected pucks: " + str(self.get_detected_pucks())) + print ("Pin offset: " + str(self.get_pin_offset())) + print ("Mount position: " + str(self.is_in_mount_position())) + print ("") + +if __name__ == "__main__": + tell = TellClient("http://Alexandres-MBP.psi.ch:8080") + tell.print_info() + + info = [ + { + "userName": "User", + "dewarName": "Dewar", + "puckName": "Puck", + "puckBarcode": "XXX0001", + "puckType": "Minispine", + "puckAddress": "", + "sampleName": "Sample", + "sampleBarcode": "YYY0001", + "samplePosition": "1", + "sampleStatus": "Present", + "sampleMountCount": "0" , + }, + ] + print (tell.get_samples_info()) + tell.set_samples_info(info) + print (tell.get_samples_info()) + + tell.abort_cmd() + + cmd = tell.move_cold() + print (tell.wait_cmd(cmd)) + + cmd = tell.trash() + print (tell.wait_cmd(cmd)) + + cmd = tell.scan_pin("A", 1, 1) + print (tell.wait_cmd(cmd)) + + cmd = tell.scan_puck("A", 1, 1) + print (tell.wait_cmd(cmd)) + + cmd = tell.mount("A", 1, 1) + print (tell.wait_cmd(cmd)) + + print ("Mounted sample: " + str(tell.get_mounted_sample())) + cmd = tell.unmount() + print (tell.wait_cmd(cmd)) + print ("Mounted sample: " + str(tell.get_mounted_sample())) diff --git a/script/client/sseclient.py b/script/client/sseclient.py new file mode 100644 index 0000000..3c42858 --- /dev/null +++ b/script/client/sseclient.py @@ -0,0 +1,163 @@ +import codecs +import re +import time +import warnings + +import six + +import requests + + +# Technically, we should support streams that mix line endings. This regex, +# however, assumes that a system will provide consistent line endings. +end_of_field = re.compile(r'\r\n\r\n|\r\r|\n\n') + +class SSEClient(object): + def __init__(self, url, last_id=None, retry=3000, session=None, chunk_size=1024, **kwargs): + self.url = url + self.last_id = last_id + self.retry = retry + self.chunk_size = chunk_size + + # Optional support for passing in a requests.Session() + self.session = session + + # Any extra kwargs will be fed into the requests.get call later. + self.requests_kwargs = kwargs + + # The SSE spec requires making requests with Cache-Control: nocache + if 'headers' not in self.requests_kwargs: + self.requests_kwargs['headers'] = {} + self.requests_kwargs['headers']['Cache-Control'] = 'no-cache' + + # The 'Accept' header is not required, but explicit > implicit + self.requests_kwargs['headers']['Accept'] = 'text/event-stream' + + # Keep data here as it streams in + self.buf = u'' + + self._connect() + + def _connect(self): + if self.last_id: + self.requests_kwargs['headers']['Last-Event-ID'] = self.last_id + + # Use session if set. Otherwise fall back to requests module. + requester = self.session or requests + self.resp = requester.get(self.url, stream=True, **self.requests_kwargs) + self.resp_iterator = self.resp.iter_content(chunk_size=self.chunk_size) + + # TODO: Ensure we're handling redirects. Might also stick the 'origin' + # attribute on Events like the Javascript spec requires. + self.resp.raise_for_status() + + def _event_complete(self): + return re.search(end_of_field, self.buf) is not None + + def __iter__(self): + return self + + def __next__(self): + decoder = codecs.getincrementaldecoder( + self.resp.encoding)(errors='replace') + while not self._event_complete(): + try: + next_chunk = next(self.resp_iterator) + if not next_chunk: + raise EOFError() + self.buf += decoder.decode(next_chunk) + + except (StopIteration, requests.RequestException, EOFError) as e: + time.sleep(self.retry / 1000.0) + self._connect() + + # The SSE spec only supports resuming from a whole message, so + # if we have half a message we should throw it out. + head, sep, tail = self.buf.rpartition('\n') + self.buf = head + sep + continue + + # Split the complete event (up to the end_of_field) into event_string, + # and retain anything after the current complete event in self.buf + # for next time. + (event_string, self.buf) = re.split(end_of_field, self.buf, maxsplit=1) + msg = Event.parse(event_string) + + # If the server requests a specific retry delay, we need to honor it. + if msg.retry: + self.retry = msg.retry + + # last_id should only be set if included in the message. It's not + # forgotten if a message omits it. + if msg.id: + self.last_id = msg.id + + return msg + + if six.PY2: + next = __next__ + + +class Event(object): + + sse_line_pattern = re.compile('(?P<name>[^:]*):?( ?(?P<value>.*))?') + + def __init__(self, data='', event='message', id=None, retry=None): + self.data = data + self.event = event + self.id = id + self.retry = retry + + def dump(self): + lines = [] + if self.id: + lines.append('id: %s' % self.id) + + # Only include an event line if it's not the default already. + if self.event != 'message': + lines.append('event: %s' % self.event) + + if self.retry: + lines.append('retry: %s' % self.retry) + + lines.extend('data: %s' % d for d in self.data.split('\n')) + return '\n'.join(lines) + '\n\n' + + @classmethod + def parse(cls, raw): + """ + Given a possibly-multiline string representing an SSE message, parse it + and return a Event object. + """ + msg = cls() + for line in raw.splitlines(): + m = cls.sse_line_pattern.match(line) + if m is None: + # Malformed line. Discard but warn. + warnings.warn('Invalid SSE line: "%s"' % line, SyntaxWarning) + continue + + name = m.group('name') + if name == '': + # line began with a ":", so is a comment. Ignore + continue + value = m.group('value') + + if name == 'data': + # If we already have some data, then join to it with a newline. + # Else this is it. + if msg.data: + msg.data = '%s\n%s' % (msg.data, value) + else: + msg.data = value + elif name == 'event': + msg.event = value + elif name == 'id': + msg.id = value + elif name == 'retry': + msg.retry = int(value) + + return msg + + def __str__(self): + return self.data diff --git a/script/client/tell.py b/script/client/tell.py new file mode 100644 index 0000000..56c70b4 --- /dev/null +++ b/script/client/tell.py @@ -0,0 +1,79 @@ +import sys +import os +import code +import readline +import rlcompleter +import atexit + +from TellClient import TellClient + +tell = TellClient("http://PC12288:8080") + +def info(): + tell.print_info() + +def help(): + print ("Commands: \n\thelp()\n\tinfo()\n\tmount(segment, puck, sample)\n\tunmount() \n\tdry() " \ + "\n\tscan(segment, puck, sample=None) \n\tmove_cold() \n\ttrash() \n\tabort() " \ + "\n\tset_pin_offset(value)") + +def assert_transfer_allowed(): + if not tell.is_in_mount_position(): + raise Exception("Gonio is not in mount position") + +def mount(segment, puck, sample): + assert_transfer_allowed() + cmd = tell.mount(segment, puck, sample, True, True, True) + print (tell.wait_cmd(cmd)) + +def unmount(): + assert_transfer_allowed() + cmd=tell.unmount(force=True) + print (tell.wait_cmd(cmd)) + +def move_cold(): + cmd=tell.move_cold() + print (tell.wait_cmd(cmd)) + +def trash(): + cmd=tell.trash() + print (tell.wait_cmd(cmd)) + +def dry(): + cmd=tell.dry() + print (tell.wait_cmd(cmd)) + +def scan(segment, puck, sample=None): + if sample is None: + cmd=tell.scan_puck(segment, puck, True) + else: + cmd=tell.scan_pin(segment, puck, sample, True) + print (tell.wait_cmd(cmd)) + +def abort(): + tell.abort_cmd() + +def set_pin_offset(value): + tell.set_pin_offset(value) + +info() +help() + +#for line in sys.stdin: +# tell.print_info() +#print ("", end='\r> ') + +historyPath = os.path.expanduser("./.history") +def save_history(historyPath=historyPath): + readline.write_history_file(historyPath) +if os.path.exists(historyPath): + readline.read_history_file(historyPath) +atexit.register(save_history) + +#vars = globals(); vars.update(locals()) +vars =locals() +readline.set_completer(rlcompleter.Completer(vars).complete) +readline.parse_and_bind("tab: complete") + +code.interact(banner = "", local=vars) + diff --git a/script/data/get_samples_info.py b/script/data/get_samples_info.py new file mode 100644 index 0000000..00a5bc3 --- /dev/null +++ b/script/data/get_samples_info.py @@ -0,0 +1,4 @@ + + + +set_return(get_samples_info(as_json=False)) \ No newline at end of file diff --git a/script/data/pucks.py b/script/data/pucks.py new file mode 100644 index 0000000..bdb925b --- /dev/null +++ b/script/data/pucks.py @@ -0,0 +1,22 @@ +def get_puck_names(): + return [str(a)+str(b) for a in BLOCKS for b in range(1,6)] + + +def get_puck_info(): + ret = [] + #for puck in get_puck_names(): + for puck in BasePlate.pucks: + ret.append({"address" : str(puck.name), "status": str(puck.status), "barcode" : str(puck.id)}) + return ret + + +def get_puck_obj(address): + return BasePlate.getChild(address) + + +def get_puck_obj_by_id(puck_id): + for puck in BasePlate.pucks: + if puck.id == puck_id: + return puck + return None + \ No newline at end of file diff --git a/script/data/samples.py b/script/data/samples.py new file mode 100644 index 0000000..1fcc400 --- /dev/null +++ b/script/data/samples.py @@ -0,0 +1,332 @@ +import json +import org.python.core.PyDictionary as PyDictionary + +SAMPLE_INFO_KEYS = ["userName", "dewarName", "puckName", "puckBarcode", "puckType", "puckAddress", + "sampleName", "samplePosition", "sampleBarcode", "sampleStatus", "sampleMountCount"] +samples_info = [] + + +def set_samples_info(info): + global samples_info + if (is_string(info)): + info = json.loads(info) + if not is_list(info): + raise Exception("Sample info must be a list (given object type is " + str(type(info)) + ")") + #Sanitize list + remove = [] + for sample in info: + try: + if set(sample.keys()) != set(SAMPLE_INFO_KEYS): + raise Exception() + except: + remove.append(sample) + for el in remove: + info.remove(el) + print "Invalid samples info element: " + str(el) + samples_info = info + save_samples_info() + #Trust beamline on assignments, so update puck info + update_puck_table() + + +def clear_samples_info(): + set_samples_info([]) + +def save_samples_info(): + data = get_samples_info(True) + output_file = open( get_context().setup.expandPath("{context}/samples_info.json") , "w") + output_file.write(data) + output_file.close() + get_context().sendEvent("samples_updated", True) + +def restore_samples_info(): + try: + inputfile = open(get_context().setup.expandPath("{context}/samples_info.json"), "r") + info = inputfile.read() + except: + print >> sys.stderr, "Error reading sample info file: " + str(sys.exc_info()[1]) + info = [] + set_samples_info(info) + +def get_samples_info(as_json=True): + global samples_info + return json.dumps(to_list(samples_info)) if as_json else samples_info + +def has_puck_datamatrix(datamatrix): + if samples_info is not None: + for si in samples_info: + if si["puckBarcode"] == datamatrix: + return True + return False + +def add_puck_datamatrix(barcode, address = "", dewar = "Unknown", user = "Unknown", puck = "Unknown", type = "unipuck", sample_prefix = "Sample"): + if has_puck_datamatrix(barcode): + raise Exception("Datamatrix already defined: " + str(barcode)) + for s in range(1,17): + info = \ + { "userName": user, \ + "dewarName": dewar, \ + "puckName": puck, \ + "puckBarcode": address if barcode is None else barcode, \ + "puckType": type, \ + "puckAddress": address,\ + "sampleName": sample_prefix + " " + str(s), \ + "samplePosition": str(s),\ + "sampleStatus": "Unknown", \ + "sampleMountCount": "0", + } + samples_info.append(info) + save_samples_info() + +def remove_puck_datamatrix(barcode): + remove = [] + for si in samples_info: + if si["puckBarcode"] == barcode: + remove.append(si) + for el in remove: samples_info.remove(el) + save_samples_info() + +def set_puck_datamatrix(puck, datamatrix): + if puck is None: + puck = "" + if datamatrix is None: + datamatrix = "" + if samples_info is not None: + for si in samples_info: + if si["puckBarcode"] == datamatrix: + si["puckAddress"] = puck + elif si["puckAddress"] == puck: + si["puckAddress"] = "" + save_samples_info() + +def reset_puck_datamatrix(puck = None): + if samples_info is not None: + for si in samples_info: + if (si["puckAddress"] == puck) or (puck is None): + si["puckAddress"] = "" + save_samples_info() + for p in BasePlate.getChildren(): + if (p.name == puck) or (puck is None): + p.id = None + +def get_puck_datamatrix(): + ret = {} + for si in samples_info: + if si["puckBarcode"] is not None and si["puckBarcode"]!="": + ret[si["puckBarcode"]] = si["puckAddress"] + return ret + +def get_puck_address(barcode): + try: + return get_puck_datamatrix()[barcode] + except: + return None + + +def update_puck_table(): + dms = get_puck_datamatrix() + for barcode in dms.keys(): + address = dms[barcode] + puck = get_puck_obj(address) + if puck is not None: + puck.id = barcode + + +#Sample mount/unmount + +def same_address(puck_add_1, sample_pos_1, puck_add_2, sample_pos_2): + if str(puck_add_1) != str(puck_add_2): + return False + try: + sample_pos_1 = int(sample_pos_1) + except: + return False + try: + sample_pos_2 = int(sample_pos_2) + except: + return False + return sample_pos_1 == sample_pos_2 + + +def update_samples_info_sample_mount(puck_address, sample_position, sample_detected, sample_id): + try: + if (samples_info is not None) and (puck_address is not None): + for si in samples_info: + if same_address( si["puckAddress"], si["samplePosition"], puck_address, sample_position): + if sample_detected: + if si["sampleStatus"] != "Mounted": + si["sampleStatus"] = "Mounted" + try: + mount_count = int(si["sampleMountCount"]) + except: + mount_count = 0 + si["sampleMountCount"] = mount_count + 1 + else: + si["sampleStatus"] = "Unknown" + + if sample_id is not None: + si["sampleBarcode"] = sample_id + + else: + if si["sampleStatus"] == "Mounted": + si["sampleStatus"] = "HasBeenMounted" + save_samples_info() + except: + pass + + +def update_samples_info_sample_unmount(puck_address, sample_position): + try: + if (samples_info is not None) and (puck_address is not None): + for si in samples_info: + if same_address( si["puckAddress"], si["samplePosition"], puck_address, sample_position): + si["sampleStatus"] = "HasBeenMounted" + save_samples_info() + return + except: + pass + +def update_samples_info_sample_scan(puck_address, sample_position, sample_detected, sample_id): + try: + if (samples_info is not None) and (puck_address is not None): + for si in samples_info: + if same_address( si["puckAddress"], si["samplePosition"], puck_address, sample_position): + if sample_detected: + if si["sampleStatus"] == "Unknown": + si["sampleStatus"] = "Present" + else: + if si["sampleStatus"] == "Present": + si["sampleStatus"] = "Unknown" + if sample_id is not None: + si["sampleBarcode"] = sample_id + save_samples_info() + return + except: + pass + + + +test_sample_data = [ \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0001", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "MySample 1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0001", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "MySample 2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0001", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "MySample 3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0001", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "MySample 4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0001", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "MySample 5", \ + "sampleBarcode": "", \ + "samplePosition": 5,\ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0002", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "MySample 1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0002", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "MySample 2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0002", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "MySample 3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0002", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "MySample 4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": "Alexandre", \ + "dewarName": "TEST", \ + "puckName": "My puck", \ + "puckBarcode": "AAA0002", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "MySample 5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + ] + \ No newline at end of file diff --git a/script/data/set_samples_info.py b/script/data/set_samples_info.py new file mode 100644 index 0000000..bc7e803 --- /dev/null +++ b/script/data/set_samples_info.py @@ -0,0 +1,4 @@ + + + +set_samples_info(args[0]) \ No newline at end of file diff --git a/script/devices/BarcodeReader.py b/script/devices/BarcodeReader.py new file mode 100644 index 0000000..5743a0c --- /dev/null +++ b/script/devices/BarcodeReader.py @@ -0,0 +1,82 @@ + + +class BarcodeReader(DeviceBase): + + def __init__(self, name, microscan, microscan_cmd): + DeviceBase.__init__(self, name) + self.microscan = microscan + self.microscan_cmd = microscan_cmd + + + def doInitialize(self): + self.disable() + self.readout = None + self.processing = False + self.task_callable=None + + def enable(self): + self.microscan_cmd.write("<H>") + self.setState(State.Ready) + + def disable(self): + self.microscan_cmd.write("<I>") + self.setState(State.Disabled) + + def get(self,timeout=1.0): + self.state.assertReady() + try: + self.setState(State.Busy) + self.microscan.flush() + ret = self.microscan.waitString(int(timeout * 1000)) + if ret is not None: + ret = ret.strip() + self.setCache(ret, None) + return ret + except: + self.setCache(None, None) + return None + finally: + if self.state == State.Busy: + self.setState(State.Ready) + + def doUpdate(self): + self.get() + + + def read(self,timeout=1.0): + if self.processing: + raise Exception("Ongoing read operation") + self.processing = True + try: + initial = self.state + if initial == State.Disabled: + self.enable() + try: + return self.get(timeout) + finally: + if initial == State.Disabled: + self.disable() + finally: + self.processing = False + + def _read_task(self, timeout): + global readout + self.readout = self.read(timeout) + return self.readout + + def start_read(self, timeout=1.0): + self.readout = None + self.task_callable = fork((self._read_task, (timeout,))) + + def get_readout(self): + return self.readout + + def wait_readout(self): + if self.task_callable is not None: + join(self.task_callable) + self.task_callable = None + return self.readout + + +add_device(BarcodeReader("barcode_reader", microscan, microscan_cmd), force = True) + \ No newline at end of file diff --git a/script/devices/Gonio.py b/script/devices/Gonio.py new file mode 100644 index 0000000..0f264f5 --- /dev/null +++ b/script/devices/Gonio.py @@ -0,0 +1,43 @@ + + +def home_fast_table(): + caput ("SAR-EXPMX1:ASYN.AOUT", "enable plc 1") + +def get_fx_pos(): + return caget("SAR-EXPMX:MOT_FX.RBV", 'f') + +def set_fx_pos(pos): + return caput("SAR-EXPMX:MOT_FX.VAL", float(pos)) + + +def get_fy_pos(): + return caget("SAR-EXPMX:MOT_FY.RBV", 'f') + +def set_fy_pos(pos): + return caput("SAR-EXPMX:MOT_FY.VAL", float(pos)) + +def get_ry_pos(): + return caget("SAR-EXPMX:MOT_ROT_Y.RBV", 'f') + +def set_ry_pos(pos): + return caput("SAR-EXPMX:MOT_ROT_Y.VAL", float(pos)) + +def get_cz_pos(): + return caget("SAR-EXPMX:MOT_CZ.RBV", 'f') + +def set_cz_pos(pos): + return caput("SAR-EXPMX:MOT_CZ.VAL", float(pos)) + +def get_cx_pos(): + return caget("SAR-EXPMX:MOT_CX.RBV", 'f') + +def set_cx_pos(pos): + return caput("SAR-EXPMX:MOT_CX.VAL", float(pos)) + + +def set_mount_position(): + set_fx_pos(0.0) + set_fy_pos(0.0) + set_ry_pos(0.0) + set_cz_pos(0.0) + set_cx_pos(0.0) \ No newline at end of file diff --git a/script/devices/Hexiposi.py b/script/devices/Hexiposi.py new file mode 100644 index 0000000..de958ed --- /dev/null +++ b/script/devices/Hexiposi.py @@ -0,0 +1,173 @@ +import ch.psi.pshell.device.DiscretePositionerBase as DiscretePositionerBase +import requests +import json + +class Hexiposi(DiscretePositionerBase): + def __init__(self, name, url): + DiscretePositionerBase.__init__(self, name, ["A","B","C","D","E","F"]) + self.PORT_SET=8002 + self.PORT_GET=8002 + if not url.startswith("http://"): + url = "http://" + url + if not url.endswith(":"): + url = url + ":" + self.url_set = url + str (self.PORT_SET)+ "/hexiposi/" + self.url_get = url + str (self.PORT_GET)+ "/hexiposi/" + self.moved = True + self.homing_state = State.Disabled + self.rback = self.UNKNOWN_POSITION + self.timeout = 3.0 + self.offline = False + + def doInitialize(self): + super(Hexiposi, self).doInitialize() + self.val = self.doReadReadback() + + def get_response(self, response): + if (response.status_code!=200): + raise Exception (response.text) + return json.loads(response.text) + + def get_status(self): + try: + self.status = self.get_response(requests.get(url=self.url_get+"get", timeout=self.timeout)) + self.estop = self.status["estop"] + self.homed = self.status["homed"] + self.error = self.status["errorCode"] + self.remote = self.status["mode"] == "remote" + self.moving = self.status["errorCode"] + self.pos = self.status["position"] + self.moving = self.status["moving"] + self.offset = self.status["offset"] + self.dpos = self.status["discretePosition"] + if (self.homed==False): rback = self.UNKNOWN_POSITION + elif self.dpos == 1: rback = "A" + elif self.dpos == 2: rback = "B" + elif self.dpos == 4: rback = "C" + elif self.dpos == 8: rback = "D" + elif self.dpos == 16: rback = "E" + elif self.dpos == 32: rback = "F" + else: rback = self.UNKNOWN_POSITION + if (rback == self.UNKNOWN_POSITION) or (rback != self.rback): + self.moved = True + self.rback = rback + self.offline = False + return self.status + except: + self.offline = True + self.updateState() + raise + + def set_deadband(self, value = 0.1): #degrees + ret = self.get_response(requests.get(url=self.url_set+"setDeadband?deadband=" + str(value), timeout=self.timeout)) + if ret["deadbandOutput"] == value: + return value + raise Excepiton("Error setting deadband: " + str(ret)) + + def move_pos(self, pos): + return self.get_response(requests.get(url=self.url_set+"set?pos=" + str(pos), timeout=self.timeout)) + + def move_home(self): + ret = self.get_response(requests.get(url=self.url_set+"set?home=1", timeout=self.timeout)) + try: + self.waitState(self.homing_state,1200) + except: + pass + return ret + + def stop_move(self): + return self.get_response(requests.get(url=self.url_set+"set?stop=1", timeout=self.timeout)) + + def set_offset(self, offset): + return self.get_response(requests.get(url=self.url_set+"setOffset?offset="+str(offset), timeout=self.timeout)) + + def doUpdate(self): + self.get_status() + super(Hexiposi, self).doUpdate() + + + def doStop(self): + self.stop_move() + + def doRead(self): + return str(self.val) + + def doReadReadback(self): + self.get_status() + return self.rback + + def doWrite(self, val): + val = ord(val) - ord('A') +1 + if val<1 or val>6: + raise Exception("Invalid value: " + str(val)) + moving = val != self.val + self.val = val + self.move_pos(self.val) + #Workaround as state does not changes immediatelly + if moving: + #try: + # self.waitState(State.Busy,1200) + #except: + # print sys.exc_info()[1] + start = time.time() + while self.state != State.Busy: + if time.time() - start > 1.5: + print "Timeout waiting Hexiposi busy" + break + self.update() + + def is_in_position(self, pos): + return self.take() == pos + + + def assert_in_position(self, pos): + if not is_in_position(pos): + raise Exception ("Hexiposi is not in position") + + def assert_homed(self): + if self.homed == False: + raise Exception ("Hexiposi is not homed") + + def assert_in_known_position(self): + self.get_status() + if self.rback == 'Unknown': + raise Exception("Hexiposi is in an unknown position, please home.") + + #def isReady(self): + # self.get_status() + # return self.moving == False + + def updateState(self): + if self.isSimulated(): + self.setState(State.Ready) + elif self.offline: + self.setState(State.Offline) + elif self.homed == False: + self.setState(self.homing_state) + elif self.moving: + self.setState(State.Busy) + else: + self.setState(State.Ready) + + + +#http://myriotell:8003/hexiposi/get +dev = Hexiposi("hexiposi", "myriotell") +#If no Rotation Lid is mounted set it to simulated +#dev.setSimulated() + +add_device(dev, True) +hexiposi.polling=1000 +#print dev.url +#print dev.get_status() + +class hexiposi_position(ReadonlyRegisterBase): + def doRead(self): + try: + return float(hexiposi.pos) + except: + return float("nan") + +add_device(hexiposi_position(), True) +hexiposi_position.polling = 1000 +hexiposi.set_deadband(0.5) diff --git a/script/devices/LaserDistance.py b/script/devices/LaserDistance.py new file mode 100644 index 0000000..97efea4 --- /dev/null +++ b/script/devices/LaserDistance.py @@ -0,0 +1,17 @@ +class LaserDistance(ReadonlyRegisterBase): + def __init__(self): + ReadonlyRegisterBase.__init__(self, "laser_distance") + def doRead(self): + ret = ue.readable.read() + ret = 0.0 if math.isnan(ret) else ret + return ret + +class ListenerAI (DeviceListener): + def onValueChanged(self, device, value, former): + laser_distance.setCache( 0.0 if math.isnan(value) else value, None) + +listenerAI = ListenerAI() +ue.addListener(listenerAI) + +laser_distance=LaserDistance() +add_device(laser_distance, True) diff --git a/script/devices/LedCtrl.py b/script/devices/LedCtrl.py new file mode 100644 index 0000000..da4e51d --- /dev/null +++ b/script/devices/LedCtrl.py @@ -0,0 +1,46 @@ +import ch.psi.pshell.device.DiscretePositionerBase as DiscretePositionerBase + + +class LedPositioner(DiscretePositionerBase): + def __init__(self): + DiscretePositionerBase.__init__(self, "led_ctrl", ["On", "Off"]) + self.setState(State.Ready) + self.val = self.doReadReadback() + + def doRead(self): + return self.val + + def doReadReadback(self): + return "On" if get_led_state() else "Off" + + def doWrite(self, val): + self.val = val + if self.val == "On": + set_led_state(True) + else: + set_led_state(False) + + +add_device(LedPositioner(), True) +led_ctrl.polling = 1000 + + + + +import ch.psi.pshell.device.ProcessVariableConfig as ProcessVariableConfig +class LedLevel(ProcessVariableBase): + def __init__(self, name): + ProcessVariableBase.__init__(self, name, ProcessVariableConfig()) + + def doRead(self): + return get_led_level() + + def doWrite(self, val): + return set_led_level(val) + +led_level = LedLevel("led_level") +led_level.config.minValue = 0.0 +led_level.config.maxValue = 100.0 +led_level.config.unit = "%" +add_device(led_level, True) +led_level.polling = 1000 \ No newline at end of file diff --git a/script/devices/OneWire.py b/script/devices/OneWire.py new file mode 100644 index 0000000..20e590f --- /dev/null +++ b/script/devices/OneWire.py @@ -0,0 +1,134 @@ +import traceback +from datetime import datetime + +class Detector(ReadonlyRegisterBase): + def __init__(self, name): + ReadonlyRegisterBase.__init__(self, name) + self.reset() + + def set_inputs(self, inputs): + self.inputs = inputs + if self.take() != inputs.values(): + self.setCache(inputs.values(), None) + if self.getParent()!=None: + self.getParent().updateCache() + if (len(self.take()) == 0): + self.setState(State.Offline) + else: + self.setState(State.Ready) + + def set_input(self, index, val): + self.inputs[index] = val + self.set_inputs(self.inputs) + + def reset(self): + self.id = None + self.sn = None + self.status = None + self.type = None + self.set_inputs({}) + +class Esera(TcpDevice): + def __init__(self, name, server, timeout = 1000, retries = 1): + TcpDevice.__init__(self, name, server) + self.setMode(self.Mode.FullDuplex) + self.detectors = [] + for i in range(30): + self.detectors.append(Detector("Detector " + str(i+1))) + self.setChildren(self.detectors) + self.completed_initializatiod = False + self.debug = False + + def start(self): + self.getLogger().info("Starting controller") + self.write("set,sys,run,1\n") + + def stop(self): + self.getLogger().info("Stopping controller") + self.write("set,sys,run,0\n") + + def list(self): + self.write("get,owb,listall1\n") + + def req_data(self): + self.write("get,sys,data\n") + + def doInitialize(self): + super(Esera, self).doInitialize() + self.init_timestamp = time.time() + try: + self.setState(State.Ready) #So can communicate + for det in self.detectors: + det.reset() + self.list() + time.sleep(1.0) + self.check_started() + self.req_data() + except: + print >> sys.stderr, traceback.format_exc() + self.getLogger().warning(traceback.format_exc()) + raise + + def doUpdate(self): + self.check_started() + self.req_data() + + def updateCache(self): + #print "Update" + cache = [] + for det in self.detectors: + cache.append(det.take()) + self.setCache(cache, None) + + + def check_started(self): + if not self.completed_initializatiod: + init = True + for det in self.detectors: + if det.id == None: + init = False + break + if init: + self.completed_initializatiod = True + print("Completed initialization") + self.getLogger().info("Completed initialization") + self.start() + + def onString(self, msg): + if self.debug: + print datetime.now() , " - " , msg + tokens = msg.split("|") + if len(tokens)>1: + try: + if msg[:3] == "LST": + #LST|1_OWD1|3AF361270000009E|S_0|DS2413| + if tokens[1] > 1: + index = int(tokens[1].split("_")[1][3:]) - 1 + if index < len(self.detectors): + det = self.detectors[index] + det.id = tokens[1] + det.sn= tokens[2] if len(tokens)>2 else None + det.status = int(tokens[3][2:]) if len(tokens)>3 else None + det.type = tokens[4] if len(tokens)>4 else None + if det.status!= 0: + det.set_inputs({}) + else: + for det in self.detectors: + if det.id is not None and msg.startswith(det.id): + det_id = int(tokens[0][len(det.id)+1:]) + det.set_input(det_id, int(tokens[1])) + except: + print >> sys.stderr, traceback.format_exc() + self.getLogger().log(traceback.format_exc()) + + + + + + + +add_device(Esera("onewire", "129.129.126.83:5000"), force = True) +onewire.setPolling(500) +add_device(onewire.detectors[0], force = True) +add_device(onewire.detectors[1], force = True) +add_device(onewire.detectors[2], force = True) diff --git a/script/devices/RobotModbus.py b/script/devices/RobotModbus.py new file mode 100644 index 0000000..cd8abaf --- /dev/null +++ b/script/devices/RobotModbus.py @@ -0,0 +1,46 @@ +class RobotModbus(DeviceBase): + def __init__(self, name): + DeviceBase.__init__(self, name) + robot_req.write(0) + + def execute(self, command, *argv): + if robot_req.read() != 0: + raise Exception("Ongoing command") + if robot_ack.read() != 0: + raise Exception("Robot is not ready") + robot_cmd.write(command) + args = [0] * robot_args.size + index = 0 + for arg in argv: + args[index] = arg + index = index + 1 + if index == robot_args.size: + raise Exception("Invalid number of arguments") + robot_args.write(to_array(args, 'i')) + try: + self.request() + err = robot_ack.take() + if err == 1: + ret = robot_ret.read() + return ret + if err == 2: + raise Exception("Invalid command: " + str(command)) + raise Exception("Unknown error: " + str(err)) + finally: + self.cancel_request() + + def request(self): + robot_req.write(1) + while robot_ack.read() == 0: + time.sleep(0.001) + + def cancel_request(self): + robot_req.write(0) + while robot_ack.read() != 0: + time.sleep(0.001) + + def mount(self, puck, sample): + return self.execute('1', '1', puck, sample) + +add_device(RobotModbus("robot_mb"), force = True) + diff --git a/script/devices/RobotMotors.py b/script/devices/RobotMotors.py new file mode 100644 index 0000000..07ba862 --- /dev/null +++ b/script/devices/RobotMotors.py @@ -0,0 +1,62 @@ + +import ch.psi.pshell.device.PositionerConfig as PositionerConfig + + + +ROBOT_MOTORS = ["x" , "y", "z", "rx", "ry", "rz"] + + +class RobotCartesianMotor (PositionerBase): + def __init__(self, robot, index): + PositionerBase.__init__(self, robot.name + "_" + ROBOT_MOTORS[index], PositionerConfig()) + self.index = index + self.robot = robot + + #ATTENTION: Always initialize cartesian motors before scanning (or call robot.set_motors_enabled(True)) + def doInitialize(self): + self.setCache(self.doRead(), None) + + def doRead(self): + return float("nan") if self.robot.cartesian_destination is None else float(self.robot.cartesian_destination[self.index]) + + def doWrite(self, value): + if self.robot.cartesian_destination is not None: + #print "Move " + ROBOT_MOTORS[self.index] + " to " + str(value) + self.robot.cartesian_destination[self.index] = float(value) + self.robot.set_pnt(robot.cartesian_destination , "tcp_p") + self.robot.movel("tcp_p", self.robot.tool , DESC_SCAN) + + def doReadReadback(self): + return float("nan") if self.robot.cartesian_pos is None else float(self.robot.cartesian_pos[self.index]) + + + + +ROBOT_JOINT_MOTORS = ["j1" , "j2", "j3", "j4", "j5", "j6"] + + +class RobotJointMotor (PositionerBase): + def __init__(self, robot, index): + PositionerBase.__init__(self, robot.name + "_" + ROBOT_JOINT_MOTORS[index], PositionerConfig()) + self.index = index + self.robot = robot + + def doInitialize(self): + self.setpoint = self.doReadReadback() + self.setCache(self.doRead(), None) + + def doRead(self): + return self.setpoint + + def doWrite(self, value): + #print "Move " + ROBOT_JOINT_MOTORS[self.index] + " to " + str(value) + self.setpoint = value + joint = self.robot.herej() + joint[self.index] = value + self.robot.set_jnt(joint, name="tcp_j") + self.robot.movej("tcp_j", self.robot.tool , DESC_SCAN) + + def doReadReadback(self): + return self.robot.herej()[self.index] if self.robot.joint_pos is None else float(self.robot.joint_pos[self.index]) + + \ No newline at end of file diff --git a/script/devices/RobotSC.py b/script/devices/RobotSC.py new file mode 100644 index 0000000..ffa35b1 --- /dev/null +++ b/script/devices/RobotSC.py @@ -0,0 +1,315 @@ +TOOL_CALIBRATION = "tCalib" +TOOL_SUNA= "tSuna" +TOOL_DEFAULT= TOOL_SUNA + +FRAME_TABLE = "fTable" + +DESC_FAST = "mFast" +DESC_SLOW = "mSlow" +DESC_SCAN = "mScan" +DESC_DEFAULT = DESC_FAST + +AUX_SEGMENT = "X" + + +DEFAULT_ROBOT_POLLING = 500 +TASK_WAIT_ROBOT_POLLING = 50 + + +run("devices/RobotTCP") + + +simulation = False + +joint_forces = False + +class RobotSC(RobotTCP): + def __init__(self, name, server, timeout = 1000, retries = 1): + RobotTCP.__init__(self, name, server, timeout, retries) + self.set_tasks(["getDewar", "putDewar", "putGonio", "getGonio", "recover", "moveDewar", "moveCold", "movePark", "moveGonio","moveHeater", "moveScanner","moveHome", "moveAux"]) + self.set_known_points(["pPark", "pGonio", "pDewar", "pGonioG", "pScan", "pHeater", "pHeat", "pHeatB", "pScanStop","pHelium", "pHome", "pCold", "pAux"]) + self.setPolling(DEFAULT_ROBOT_POLLING) + #self.setSimulated() + + def move_dewar(self): + self.start_task('moveDewar') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_dewar() + + def move_cold(self): + self.start_task('moveCold') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_cold() + + def move_home(self): + self.start_task('moveHome') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_home() + + def get_dewar(self, segment, puck, sample): + segment = self.toSegmentNumber(segment) + self.start_task('getDewar',segment, puck, sample, is_room_temp()) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_dewar() + + def put_dewar(self, segment, puck, sample): + segment = self.toSegmentNumber(segment) + self.assert_dewar() + self.start_task('putDewar',segment, puck, sample, is_room_temp()) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + #self.assert_dewar() + self.assert_cold() + + def put_gonio(self): + pin_offset = get_pin_offset() + pin_angle_offset = get_pin_angle_offset() + print "Pin offset = " + str(pin_offset) + self.start_task('putGonio', pin_offset) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_gonio() + + def get_gonio(self): + pin_offset = get_pin_offset() + print "Pin offset = " + str(pin_offset) + self.start_task('getGonio', pin_offset) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_gonio() + + def get_aux(self, sample): + self.assert_aux() + self.start_task('getAuxiliary', sample) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_aux() + + def put_aux(self, sample): + self.assert_aux() + self.start_task('putAuxiliary', sample) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_aux() + + def move_scanner(self): + self.start_task('moveScanner') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_scanner() + + #def do_scan(self): + # self.start_task('doScan') + # self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + # self.assert_scan_stop() + + def move_gonio(self): + self.start_task('moveGonio') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_gonio() + + + def move_park(self): + self.start_task('movePark') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_park() + + def move_heater(self, speed=-1, to_bottom=True): + self.start_task('moveHeater', speed, to_bottom) + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + if to_bottom: + self.assert_heater_bottom() + else: + self.assert_heater() + + + def robot_recover(self): + self.start_task('recover') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_home() + + def move_aux(self): + self.start_task('moveAux') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_aux() + + def get_calibration_tool(self): + self.start_task('getCalTool') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_scanner() + + def put_calibration_tool(self): + self.start_task('putCalTool') + self.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + self.assert_scanner() + + + + def toSegmentNumber(self, segment): + if is_string(segment): + segment = ord(segment.upper()) - ord('A') +1 + return segment + + + def on_event(self,ev): + #print "EVT: " + ev + pass + def on_change_working_mode(self, working_mode): + if get_device("hexiposi") is not None: + hexiposi.moved = True #Force image processing on first sample + + def doUpdate(self): + #start = time.time() + RobotTCP.doUpdate(self) + global simulation + if not simulation: + if joint_forces: + if self.state != State.Offline: + self.get_joint_forces() + for dev in [jf1, jf2, jf3, jf4,jf5, jf6, jfc]: + dev.update() + #print time.time() -start + + def start_task(self, program, *args, **kwargs): + #TODO: Check safe position + return RobotTCP.start_task(self, program, *args, **kwargs) + + def stop_task(self): + RobotTCP.stop_task(self) + #TODO: Restore safe position + + + def set_remote_mode(self): + robot.set_profile("remote") + + def set_local(self): + robot.set_profile("default") + + def is_park(self): + return self.is_in_point("pPark") + + def is_cold(self): + return self.is_in_point("pCold") + + def is_home(self): + return self.is_in_point("pHome") + + def is_dewar(self): + return self.is_in_point("pDewar") + + def is_heater(self): + return self.is_in_point("pHeat") + + def is_heater_home(self): + return self.is_in_point("pHeater") + + def is_heater_bottom(self): + return self.is_in_point("pHeatB") + + def is_gonio(self): + return self.is_in_point("pGonio") + + def is_helium(self): + return self.is_in_point("pHelium") + + def is_scanner(self): + return self.is_in_point("pScan") + + def is_aux(self): + return self.is_in_point("pAux") + + #def is_scan_stop(self): + # return self.is_in_point("pScanStop") + + def is_cleared(self): + #return self.is_home() or self.is_park() or self.is_dewar() or self.is_dewar_home() + return self.get_current_point() is not None + + def assert_heater_home(self): + self.assert_in_point("pHeater") + + def assert_cold(self): + self.assert_in_point("pCold") + + def assert_heater(self): + self.assert_in_point("pHeat") + + def assert_heater_bottom(self): + self.assert_in_point("pHeatB") + + def assert_park(self): + self.assert_in_point("pPark") + + def assert_home(self): + self.assert_in_point("pHome") + + def assert_dewar(self): + self.assert_in_point("pDewar") + + def assert_gonio(self): + self.assert_in_point("pGonio") + + def assert_helium(self): + self.assert_in_point("pHelium") + + def assert_scanner(self): + self.assert_in_point("pScan") + + def assert_aux(self): + self.assert_in_point("pAux") + + #def assert_scan_stop(self): + # self.assert_in_point("pScanStop") + + def assert_cleared(self): + if not self.is_cleared(): + raise Exception("Robot not in cleared position") + + def wait_ready(self): + robot.waitState(State.Ready, 1000) #robot.state.assertReady() + +if simulation: + add_device(RobotSC("robot","localhost:1000"),force = True) +else: + #add_device(RobotSC("robot", "129.129.243.120:1000"), force = True) + #add_device(RobotSC("robot", "pcp068129.psi.ch:1000"), force = True) + #add_device(RobotSC("robot", "saresb-cons-06.psi.ch:1000"), force = True) + add_device(RobotSC("robot", "129.129.243.90:1000"), force = True) + + +robot.set_default_desc(DESC_DEFAULT) +robot.default_speed = 20 +robot.set_frame(FRAME_DEFAULT) +robot.set_tool(TOOL_DEFAULT) +robot.setPolling(DEFAULT_ROBOT_POLLING) + +robot.get_current_point() #TODO: REMOVE WHEN CURRENT POINT REPORTED BY POLLING MESSAGE + +class jf1(ReadonlyRegisterBase): + def doRead(self): + return None if robot.joint_forces == None else robot.joint_forces[0] +class jf2(ReadonlyRegisterBase): + def doRead(self): + return None if robot.joint_forces == None else robot.joint_forces[1] +class jf3(ReadonlyRegisterBase): + def doRead(self): + return None if robot.joint_forces == None else robot.joint_forces[2] +class jf4(ReadonlyRegisterBase): + def doRead(self): + return None if robot.joint_forces == None else robot.joint_forces[3] +class jf5(ReadonlyRegisterBase): + def doRead(self): + return None if robot.joint_forces == None else robot.joint_forces[4] +class jf6(ReadonlyRegisterBase): + def doRead(self): + return None if robot.joint_forces == None else robot.joint_forces[5] +class jfc(ReadonlyRegisterBase): + def doRead(self): + if robot.joint_forces == None: + return float('NaN') + if robot.powered == False: + return float('NaN') + return (robot.joint_forces[1]+74)/4 + (robot.joint_forces[2]+30)/4 + (robot.joint_forces[4]-0.8)/0.2 + +if joint_forces: + add_device(jf1(), force = True) + add_device(jf2(), force = True) + add_device(jf3(), force = True) + add_device(jf4(), force = True) + add_device(jf5(), force = True) + add_device(jf6(), force = True) + add_device(jfc(), force = True) \ No newline at end of file diff --git a/script/devices/RobotTCP.py b/script/devices/RobotTCP.py new file mode 100644 index 0000000..34e9e8c --- /dev/null +++ b/script/devices/RobotTCP.py @@ -0,0 +1,865 @@ +import threading + +FRAME_DEFAULT = "world" +FLANGE = "flange" + +MAX_NUMBER_PARAMETERS = 20 + +run("devices/RobotMotors") + +class RobotTCP(TcpDevice, Stoppable): + def __init__(self, name, server, timeout = 1000, retries = 1): + TcpDevice.__init__(self, name, server) + self.timeout = timeout + self.retries = retries + self.header = None + self.trailer = "\n" + self.array_separator = '|' + self.cmd_separator = ' ' + self.msg_id = 0 + self.working_mode = "invalid" + self.status = "invalid" + self.powered = None + self.settled = None + self.empty = None + self.working_mode = None + self.status = None + self.lock = threading.Lock() + self.joint_forces = None + self.current_task = None + self.current_task_ret = None + self.high_level_tasks = [] + self.known_points = [] + self.current_points = [] + self.cartesian_destination = None + #self.flange_pos = [None] * 6 + self.cartesian_pos = [None] * 6 + self.joint_pos = [None] * 6 + self.cartesian_motors_enabled = False + self.cartesian_motors = [] + self.joint_motors_enabled = False + self.joint_motors = [] + self.tool = None + self.default_desc = None + self.tool_open = None + #self.tool_trsf = [0.0] * 6 + self.frame = FRAME_DEFAULT + self.polling_interval = 0.01 + self.reset = True + self.default_tolerance = 5 + self.default_speed = 100 + + self.task_start_retries = 3 + self.exception_on_task_start_failure = True #Tasks may start and be finished when checked + + + def doInitialize(self): + super(RobotTCP, self).doInitialize() + self.reset = True + + def set_tool(self, tool): + self.tool = tool + #self.tool_trsf = self.get_tool_trsf() + self.evaluate("tcp_curtool=" + tool) + if self.cartesian_motors_enabled: + self.update() + self.set_motors_enabled(True) + self.is_tool_open() + + def get_tool(self): + return self.tool + + def set_frame(self, frame): + self.frame = frame + self.evaluate("tcp_curframe=" + frame) + if self.cartesian_motors_enabled: + self.update() + self.set_motors_enabled(True) + self.waitCacheChange(5000) + + def get_frame(self): + return self.frame + + def set_default_frame(self): + self.set_frame(FRAME_DEFAULT) + + def assert_tool(self, tool=None): + if tool is None: + if self.tool is None: + raise Exception("Tool is undefined") + elif self.tool != tool: + raise Exception("Invalid tool: " + self.tool) + + def set_default_desc(self,default_desc): + self.default_desc=default_desc + + def get_default_desc(self): + return self.default_desc + + def set_tasks(self,tasks): + self.high_level_tasks=tasks + + def get_tasks(self): + return self.high_level_tasks + + def set_known_points(self, points): + self.known_points=points + + def get_known_points(self): + return self.known_points + + def get_current_points(self, tolerance = None): + ret = self.is_in_points(*self.known_points, tolerance = tolerance) + current_points = [] + for i in range(len(ret)): + if ret[i] == True: + current_points.append(self.known_points[i]) + return current_points + + def get_current_point(self, tolerance = None): + current_points = self.get_current_points(tolerance) + if (current_points is not None) and ( len(current_points) >0): + return current_points[0] + return None + + def get_current_points_cached(self): + return self.current_points + + def get_current_point_cached(self): + if (self.current_points is not None) and (len (self.current_points) >0): + return self.current_points[0] + return None + + def assert_in_known_point(self, tolerance = None): + if self.get_current_point(tolerance) is None: + raise Exception ("Robot not in known point") + + def _sendReceive(self, msg_id, msg = "", timeout = None): + tx = self.header if (self.header != None) else "" + tx = tx + msg_id + " " + msg + if (len(tx)>150): + raise Exception("Exceeded maximum message size") + self.getLogger().finer("TX = '" + str(tx)+ "'") + if (self.trailer != None): tx = tx + self.trailer + if self.isSimulated(): + return "" + rx = self.sendReceive(tx, msg_id, self.trailer , 0, self.timeout if timeout is None else timeout, self.retries) + rx=rx[:-1] #Remove 0A + self.getLogger().finer("RX = '" + str(rx) + "'") + if rx[:3] != msg_id: + if (time.time()-start) >= timeout: + raise Exception("Received invalid message id: " + str(rx[:3]) + " - expecting:" + msg_id ) + if len(rx)<4: + raise Exception("Invalid message size: " + str(len(rx)) ) + if rx[3] == "*": + raise Exception(rx[4:]) + return rx[4:] + + def call(self, msg, timeout = None): + self.lock.acquire() + try: + id = "%03d" % self.msg_id + self.msg_id = (self.msg_id+1)%1000 + return self._sendReceive(id, msg, timeout) + finally: + self.lock.release() + + def execute(self, command, *args, **kwargs): + timeout = None if (kwargs is None) or (not kwargs.has_key("timeout")) else kwargs["timeout"] + msg = str(command) + if len(args)>MAX_NUMBER_PARAMETERS: + raise Exception("Exceeded maximum number of parameters") + for i in range(len(args)): + msg += (self.cmd_separator if (i==0) else self.array_separator) + str(args[i]) + rx = self.call(msg, timeout) + if rx.count(self.array_separator)>0: + return rx.split(self.array_separator) + return rx + + def evaluate(self, cmd, timeout=None): + ret = self.execute('eval', cmd, timeout=timeout) + if is_string(ret): + if ret.strip() != "": raise Exception(ret) + + def get_var(self, name): + return self.execute('get_var', name) + + #Makes app crash + #def get_str(self, name='s'): + # return self.execute('get_str', name) + + def get_arr(self, name, size): + return self.execute('get_arr', name, size) + + def get_bool(self, name = "tcp_b"): + return True if (self.execute('get_bool', name).strip() == '1') else False + + def get_int(self, name ="tcp_n"): + return int(self.get_var(name)) + + def get_float(self, name ="tcp_n"): + return float(self.get_var(name)) + + def get_int_arr(self, size, name="tcp_a"): + # not working. A Jython bug in PyUnicaode? + #return [int(x) for x in self.get_arr("tcp_a", size)] + ret = [] + a=self.get_arr(name, size) + for i in range(size): + ret.append(int(a[i])) + return ret + + def get_float_arr(self, size, name="tcp_a"): + #return [float(x) for x in self.get_arr("tcp_a", size)] + a=self.get_arr(name, size) + ret = []; + for i in range(size): ret.append(float(a[i])); + return ret + + def get_trsf(self, name="tcp_t"): + a = self.execute('get_trf', name) + ret = [] + for i in range(6): ret.append(float(a[i])) + return ret + + def set_trsf(self, l, name="tcp_t"): + self.evaluate(name + "={" + str(l[0]) + ","+ str(l[1]) + ","+ str(l[2]) + ","+ str(l[3]) + ","+ str(l[4]) + ","+ str(l[5]) + "}") + + def get_jnt(self, name="tcp_j"): + a = self.execute('get_jnt', name) + ret = [] + for i in range(6): ret.append(float(a[i])) + return ret + + def set_jnt(self, l, name="tcp_j"): + self.evaluate(name + "={" + str(l[0]) + ","+ str(l[1]) + ","+ str(l[2]) + ","+ str(l[3]) + ","+ str(l[4]) + ","+ str(l[5]) + "}") + + def get_pnt(self, name="tcp_p"): + #a = self.execute('get_pnt', name) + #ret = [] + #for i in range(6): ret.append(float(a[i])) + #return ret + return self.get_trsf(name+".trsf") + + #trsf = (x,y,z,rx,ry,rz) + #TODO: config = (shoulder, elbow, wrist) + def set_pnt(self, trsf, name="tcp_p", config=None): + self.set_trsf(trsf, name+".trsf") + + def get_tool_trsf(self, name=None): + if name is None: + self.assert_tool() + name = self.tool + return self.get_trsf(name+".trsf") + + def set_tool_trsf(self, trsf, name=None): + if name is None: + self.assert_tool() + name = self.tool + self.set_trsf(trsf, name+".trsf") + + def eval_int(self, cmd): + if self.isSimulated(): + return 0 + self.evaluate("tcp_n=" + cmd) + return self.get_int() + + def eval_float(self, cmd): + if self.isSimulated(): + return 0.0 + self.evaluate("tcp_n=" + cmd) + return self.get_float() + + def eval_bool(self, cmd): + if self.isSimulated(): + return False + self.evaluate("tcp_b=" + cmd) + return self.get_bool() + + #def eval_str(self, cmd): + # self.evaluate("s=" + cmd) + # return self.get_str() + + def eval_jnt(self, cmd): + self.evaluate("tcp_j=" + cmd) + return self.get_jnt() + + def eval_trf(self, cmd): + self.evaluate("tcp_t=" + cmd) + return self.get_trsf() + + def eval_pnt(self, cmd): + self.evaluate("tcp_p=" + cmd) + return self.get_pnt() + + + #Robot control + def is_powered(self): + self.powered = self.eval_bool("isPowered()") + return self.powered + + def enable(self): + if not self.is_powered(): + self.evaluate("enablePower()") + time.sleep(1.0) + if not self.is_powered(): + raise Exception("Cannot enable power") + + #waits for power to be actually cut off + def disable(self): + self.evaluate("disablePower()", timeout=5000) + + def get_monitor_speed(self): + self.speed = self.eval_int("getMonitorSpeed()") + return self.speed + + def set_monitor_speed(self, speed): + ret = self.eval_int("setMonitorSpeed(" + str(speed) + ")") + if (ret==-1): raise Exception("The robot is not in remote working mode") + if (ret==-2): raise Exception("The monitor speed is under the control of the operator") + if (ret==-3): raise Exception("The specified speed is not supported") + + def set_default_speed(self): + set_monitor_speed(self.default_speed) + + def is_calibrated(self): + return self.eval_bool("isCalibrated()") + + def save_program(self): + ret = self.execute('save', timeout=5000) + if str(ret) != "0": raise Exception("Error saving program: " + str(ret)) + + def _update_working_mode(self, mode, status): + cur_mode = self.working_mode + if mode==1: + self.working_mode = "manual" + self.status = "hold" if status==6 else "move" + elif mode==2: + self.working_mode = "test" + self.status = "hold" if status==3 else "move" + elif mode==3: + self.working_mode = "local" + self.status = "hold" if status==2 else "move" + elif mode==4: + self.working_mode = "remote" + self.status = "hold" if status==2 else "move" + else: + self.working_mode = "invalid" + self.status = "invalid" + if self.working_mode != cur_mode: + try: + self.on_change_working_mode(self.working_mode) + except: + pass + + def read_working_mode(self): + try: + mode = self.eval_int("workingMode(tcp_a)") + status = int(self.get_var("tcp_a[0]")) + self._update_working_mode(mode, status) + self._update_state() + except: + self.working_mode = "invalid" + self.status = "invalid" + return self.working_mode + + def get_emergency_stop_sts(self): + st = self.eval_int("esStatus()") + if (st== 1): return "active" + if (st== 2): return "activated" + return "off" + + def get_safety_fault_signal(self): + fault = self.eval_bool("safetyFault(s)") + #if (fault): + # return get_str() + return fault + + #Motion control + def stop(self): + self.evaluate("stopMove()") + + def resume(self): + self.evaluate("restartMove()") + + def reset_motion(self, joint=None): + self.evaluate("resetMotion()" if (joint is None) else ("resetMotion(" + joint + ")")) + + def is_empty(self): + self.empty = self.eval_bool("isEmpty()") + self._update_state() + return self.empty + + def is_settled(self): + self.settled = self.eval_bool("isSettled()") + self._update_state() + return self.settled + + def get_move_id(self): + return self.eval_int("getMoveId()") + + def set_move_id(self, id): + return self.evaluate("setMoveId(" + str(id) + " )") + + def get_joint_forces(self): + try: + self.evaluate("getJointForce(tcp_a)") + self.joint_forces = self.get_float_arr(6) + return self.joint_forces + except: + self.joint_forces = None + raise + + def movej(self, joint_or_point, tool=None, desc=None, sync=False): + if desc is None: desc = self.default_desc + if tool is None: tool = self.tool + #If joint_or_point is a list assumes ir is a point + if not is_string(joint_or_point): + robot.set_pnt(joint_or_point , "tcp_p") + joint_or_point = "tcp_p" + ret = self.eval_int("movej(" + joint_or_point + ", " + tool + ", " + desc +")") + if sync: + self.wait_end_of_move() + return ret + + def movel(self, point, tool=None, desc=None, sync=False): + if desc is None: desc = self.default_desc + if tool is None: tool = self.tool + if not is_string(point): + robot.set_pnt(point , "tcp_p") + point = "tcp_p" + ret = self.eval_int("movel(" + point + ", " + tool + ", " + desc +")") + if sync: + self.wait_end_of_move() + return ret + + def movec(self, point_interm, point_target, tool=None, desc=None, sync=False): + if desc is None: desc = self.default_desc + if tool is None: tool = self.tool + ret = self.eval_int("movec(" + point_interm + ", " + point_target + ", " + tool + ", " + desc +")") + if sync: + self.wait_end_of_move() + return ret + + def wait_end_of_move(self): + time.sleep(0.05) + self.update() + #time.sleep(0.01) + #self.waitCacheChange(-1) + self.waitReady(-1) + #self.waitState(State.Ready, -1) + + + #Tool - synchronized as can freeze communication + """ + def open_tool(self, tool=None, timeout=3000): + #This function can timeout since it synchronizes move. Checking state before otherwise it can freeze the communication. + self.waitState(State.Ready, -1) + if tool is None: tool = self.tool + return self.evaluate("open(" + tool + " )", timeout=timeout) + + def close_tool(self, tool=None, timeout=3000): + #This function can timeout since it synchronizes move. Checking state before otherwise it can freeze the communication. + self.waitState(State.Ready, -1) + if tool is None: tool = self.tool + return self.evaluate("close(" + tool + " )", timeout=timeout) + """ + #Tool - Not synchronized calls: atention to open/close only when state is Ready + def open_tool(self, tool=None): + if tool is None: tool = self.tool + self.evaluate(tool + ".gripper=true") + self.tool_open = True + + def close_tool(self, tool=None): + if tool is None: tool = self.tool + self.evaluate(tool + ".gripper=false") + self.tool_open = False + + def is_tool_open(self, tool=None): + if tool is None: tool = self.tool + self.tool_open = robot.eval_bool(tool + ".gripper") + return self.tool_open + + + #Arm position + def herej(self): + return self.eval_jnt("herej()") + + def distance_t(self, trsf1, trsf2): + return self.eval_float("distance(" + trsf1 + ", " + trsf2 + ")") + + def distance_p(self, pnt1, pnt2): + return self.eval_float("distance(" + pnt1 + ", " + pnt2 + ")") + + def compose(self, pnt, frame = None, trsf = "tcp_t"): + if frame is None: frame = self.frame + return self.eval_pnt("compose(" + pnt + ", " + frame + ", " + trsf + ")") + + def here(self, tool=None, frame=None): + if tool is None: tool = self.tool + if frame is None: frame = self.frame + return self.eval_pnt("here(" + tool + ", " + frame + ")") + + def joint_to_point(self, tool=None, frame=None, joint="tcp_j"): + if tool is None: tool = self.tool + if frame is None: frame = self.frame + return self.eval_pnt("jointToPoint(" + tool + ", " + frame + ", " + joint +")") + + def point_to_joint(self, tool=None, initial_joint="tcp_j", point="tcp_p"): + if tool is None: tool = self.tool + if self.eval_bool("pointToJoint(" + tool + ", " + initial_joint + ", " + point +", j)"): + return self.get_jnt() + + def position(self, point, frame=None): + if frame is None: frame = self.frame + return self.eval_trf("position(" + point + ", " + frame + ")") + + #Profile + def get_profile(self): + return self.execute('get_profile', timeout=2000) + + def set_profile(self, name, pwd = ""): + self.execute('set_profile', str(name), str(pwd), timeout=5000) + + + #Task control + def task_create(self, program, *args, **kwargs): + program = str(program) + priority = 10 if (kwargs is None) or (not kwargs.has_key("priority")) or (kwargs["priority"] is None) else kwargs["priority"] + name = str(program if (kwargs is None) or (not kwargs.has_key("name")) else kwargs["name"]) + + if self.get_task_status(name)[0] != -1: + raise Exception("Task already exists: " + name) + + if priority<1 or priority > 100: + raise Exception("Invalid priority: " + str(priority)) + + cmd = 'taskCreate "' + name + '", ' + str(priority) + ', ' + program + '(' + for i in range(len(args)): + val = args[i] + if type(val) == bool: + if val == True: val = "true" + elif val == False: val = "false" + cmd += str(val) + (',' if (i<(len(args)-1)) else '') + cmd+=')' + self.evaluate(cmd) + + def task_suspend(self, name): + self.evaluate('taskSuspend("' + str(name)+ '")') + + #waits until the task is ready for restart + def task_resume(self, name): + self.evaluate('taskResume("' + str(name)+ '",0)', timeout = 2000) + + #waits for the task to be actually killed + def task_kill(self, name): + #self.evaluate('taskKill("' + str(name)+ '")', timeout = 5000) + self.execute('kill', str(name), timeout=5000) + + def get_task_status(self, name): + if self.isSimulated(): + return (-1,"Stopped") + code = self.eval_int('taskStatus("' + str(name)+ '")') + #TODO: String assignments in $exec causes application to freeze + #status = self + if code== -1: status = "Stopped" + elif code== 0: status = "Paused" + elif code== 1: status = "Running" + #else: status = self.execute('get_help', code) + else: status = "Error" + return (code,status) + + def get_tasks_status(self, *pars): + ret = self.execute("task_sts", *pars) + ret = ret[0:len(pars)] + for i in range(len(ret)): + try: + ret[i] = int(ret[i]) + except: + ret[i] = None + return ret + + def _update_state(self): + #self.setState(State.Busy if self.status=="move" else State.Ready) + if self.state==State.Offline: + print "Communication resumed" + if self.reset or (self.state==State.Offline): + self.check_task() + if self.current_task is not None: + print "Ongoing task: " + self.current_task + if (not self.settled) or (self.current_task is not None): self.setState(State.Busy) + elif not self.empty: self.setState(State.Paused) + else: self.setState(State.Ready) + + def doUpdate(self): + try: + start = time.time() + cur_task = self.current_task #Can change in background so cache it + if self.isSimulated(): + sts = [1, 1,"1", 100, "1", "1", 0, 0, \ + 0, 0, 0, 0, 0, 0, \ + 0, 0, 0, 0, 0, 0, \ + ] + else: + sts = self.execute("get_status", cur_task) + self._update_working_mode(int(sts[0]), int(sts[1])) + self.powered = sts[2] == "1" + self.speed = int(sts[3]) + self.empty = sts[4] == "1" + self.settled = sts[5] == "1" + + #TODO: add tool open + if cur_task is not None: + if int(sts[6]) < 0: + log("Task "+ str(cur_task) + " finished with code: " + str(sts[7]), False) + try: + self.current_task, self.current_task_ret = None, int(sts[7]) + except: + self.current_task, self.current_task_ret = None, None + for i in range(6): + self.joint_pos[i] = float(sts[8 + i]) + for i in range(6): + self.cartesian_pos[i] = float(sts[14 + i]) + + ev_index = 20 #7 + ev = sts[ev_index] if len(sts)>ev_index else "" + if len(ev.strip()) >0: + self.getLogger().info(ev) + self.on_event(ev) + + self._update_state() + self.reset = False + self.setCache({"powered": self.powered, + "speed": self.speed, + "empty": self.empty, + "settled": self.settled, + "task": cur_task, + "mode": self.working_mode, + "status": self.status, + "open": self.tool_open, + "pos": self.get_current_point_cached() if self.state==State.Ready else None #TODO: make it calculated in robot by polling funtion + }, None) + + if self.cartesian_motors_enabled: + for m in self.cartesian_motors: + m.readback.update() + + if self.joint_motors_enabled: + for m in self.joint_motors: + m.readback.update() + + except: + if self.state != State.Offline: + print >> sys.stderr, "Update error: " + str(sys.exc_info()[1]) + self.setState(State.Offline) + + #Cartesian space + def get_flange_pos(self): + return self.eval_pnt("jointToPoint(" +FLANGE + ", " + self.frame + ", herej())") + + def get_cartesian_pos(self): + self.assert_tool() + return self.eval_pnt("jointToPoint(" + self.tool + ", " + self.frame + ", herej())") + #self.set_jnt(self.herej()) + #return self.joint_to_point(tool, frame) + + def get_cartesian_destination(self): + self.assert_tool() + return self.here(self.tool, self.frame) + + def get_distance_to_pnt(self, name): + #self.here(self.tool, self.frame) #??? + self.get_cartesian_pos() + return self.distance_p("tcp_p", name) + + def is_in_point(self, p, tolerance = None): #Tolerance in mm + if (tolerance is None) and p in self.known_points: + #If checking a known point with default tolerance, updates the position cache + return p in self.get_current_points() + tolerance = self.default_tolerance if tolerance == None else tolerance + d = self.get_distance_to_pnt(p) + if d<0: + raise Exception ("Error calculating distance to " + p + " : " + str(d)) + return d<tolerance + + def get_distance_to_pnts(self, *pars): + ret = self.execute("dist_pnt", *pars) + ret = ret[0:len(pars)] + for i in range(len(ret)): + try: + ret[i] = float(ret[i]) + except: + ret[i] = None + return ret + + def is_in_points(self, *pars, **kwargs): #Tolerance in mm + tolerance = self.default_tolerance if (kwargs is None) or (not kwargs.has_key("tolerance")) or (kwargs["tolerance"] is None) else kwargs["tolerance"] + ret = self.get_distance_to_pnts(*pars) + for i in range(len(ret)): + if ret[i]<0: + ret[i] = None + else: + ret[i] = ret[i]<tolerance + if (tolerance == self.default_tolerance) and (set(self.known_points).issubset(set(pars))): #Only update cache if tolerance is default + current_points = [] + for i in range(len(ret)): + if ret[i] == True: + current_points.append(self.known_points[i]) + self.current_points = current_points + return ret + + def assert_in_point(self, p, tolerance = None): #Tolerance in mm + if not self.is_in_point(p, tolerance): + raise Exception ("Not in position " + p) + + + #Cartesian peudo-motors + def set_motors_enabled(self, value): + if value !=self.cartesian_motors_enabled: + self.cartesian_motors_enabled = value + if value: + for i in range(6): + self.cartesian_motors.append(RobotCartesianMotor(self, i)) + add_device(self.cartesian_motors[i], True) + self.cartesian_destination = self.get_cartesian_destination() + else: + for m in self.cartesian_motors: + remove_device(m) + self.cartesian_motors = [] + self.cartesian_destination = None + else: + if value: + self.cartesian_destination = self.get_cartesian_destination() + for m in self.cartesian_motors: + m.initialize() + + + #Cartesian peudo-motors + def set_joint_motors_enabled(self, value): + if value !=self.joint_motors_enabled: + self.joint_motors_enabled = value + if value: + for i in range(6): + self.joint_motors.append(RobotJointMotor(self, i)) + add_device(self.joint_motors[i], True) + else: + for m in self.joint_motors: + remove_device(m) + self.joint_motors = [] + else: + if value: + for m in self.joint_motors: + m.initialize() + #Alignment + def align(self, point = None, frame = None, desc = None): + if frame is None: frame = self.frame + self.assert_tool() + if desc is None: desc = self.default_desc + if point is None: + self.get_cartesian_pos() + else: + self.set_pnt(point) + np=self.eval_trf('align(tcp_p.trsf, ' + frame + '.trsf)') + self.set_pnt(np) + self.movej("tcp_p", self.tool, desc) + #TODO: The first command is not executed (but receive a move id) + self.movej("tcp_p", self.tool, desc, sync = True) + return np + + #High-level, exclusive motion task. + def start_task(self, program, *args, **kwargs): + tasks = [t for t in self.high_level_tasks] + if (self.current_task is not None) and (not self.current_task in tasks): + tasks.append(self.current_task) + if not program in tasks: + tasks.append(program) + #for task in tasks: + # if self.get_task_status(task)[0]>=0: + # raise Exception("Ongoing high-level task: " + task) + ts = self.get_tasks_status(*tasks) + for i in range(len(ts)): + if ts[i] > 0: + raise Exception("Ongoing high-level task: " + tasks[i]) + + self.clear_task_ret() + + for i in range(self.task_start_retries): + self.task_create(program, *args, **kwargs) + (code, status) = self.get_task_status(program) + if code>=0: break + if i < self.task_start_retries-1: + ret = self.get_task_ret(False) + if ret == 0: #Did't start + log("Retrying starting : " + str(program) + str(args) + " - status: " + str(status) + " (" + str(code) + ")", False) + print "Retrying starting : " + str(program) + str(args) + " - status: " + str(status) + " (" + str(code) + ")" + else : + print "Retrying aborted : " + str(program) + str(args) + " - ret: " + str(ret) + " - status: " + str(status) + " (" + str(code) + ")" + break + else: + log("Failed starting : " + str(program) + str(args), False) + print "Failed starting : " + str(program) + str(args) + if self.exception_on_task_start_failure: + raise Exception("Cannot start task: " + program + str(args)) + + log("Task started: " + str(program) + str(args) + " - status: " + str(status) + " (" + str(code) + ")", False) + self.current_task, self.current_task_ret = program, None + self.update() + #self._update_state() + + #TODO: remove + if self.current_task is None: + log("Task finished in first polling : " + str(program) , False) + print "Task finished in first polling : " + str(program) + + return code + + def stop_task(self): + tasks = [t for t in self.high_level_tasks] + if (self.current_task is not None) and (not self.current_task in tasks): + tasks.append(self.current_task) + for task in tasks: + #if self.get_task_status(task)[0]>=0: + self.task_kill(task) + self.reset_motion() + + def get_task_ret(self, cached = True): + return self.current_task_ret if cached else self.eval_int("tcp_ret") + + def clear_task_ret(self): + return self.evaluate("tcp_ret=0") + + def get_task(self): + return self.current_task + + def check_task(self): + if self.current_task is None: + for task in self.high_level_tasks: + if self.get_task_status(task)[0]>=0: + self.current_task, self.current_task_ret = task, None + log("Task detected: " + str(self.current_task), False) + return self.current_task + + def wait_task_finished (self, polling = None): + cur_polling = self.polling + if polling is not None: + self.polling = polling + try: + while self.get_task() != None: + time.sleep(self.polling_interval) + finally: + if polling is not None: + self.polling = cur_polling + ret = self.get_task_ret() + return ret + + def assert_no_task(self): + task = self.check_task() + if task != None: + raise Exception("Ongoing task: " + task) + + def on_event(self,ev): + pass + + def on_change_working_mode(self, working_mode): + pass + \ No newline at end of file diff --git a/script/devices/SmartMagnet.py b/script/devices/SmartMagnet.py new file mode 100644 index 0000000..0736fdf --- /dev/null +++ b/script/devices/SmartMagnet.py @@ -0,0 +1,129 @@ +class SmartMagnet(DeviceBase): + def __init__(self, name): + #DeviceBase.__init__(self, name, get_context().pluginManager.getDynamicClass("SmartMagnetConfig")()) + DeviceBase.__init__(self, name, DeviceConfig({ + "holdingCurrent":0.0, + "restingCurrent":0.0, + "mountCurrent":0.0, + "unmountCurrent":0.0, + "reverseCurrent":0.0, + "reverseTime":0.0, + })) + + def doInitialize(self): + super(SmartMagnet, self).doInitialize() + self.get_current() + + def set_current(self, current): + self.setCache(current, None) + smc_current.write(current) + + def get_current(self): + cur = smc_current.read() + self.setCache(cur, None) + return cur + + def get_current_rb(self): + self.assert_status() + return smc_current_rb.read() + + def get_status(self): + return smc_magnet_status.read() + + def assert_status(self): + pass + #if self.get_status() == False: + # raise Exception("Smart Magnet is in faulty status.") + + def is_mounted(self): + self.assert_status() + m1 = smc_mounted_1.read() + m2 = smc_mounted_2.read() + if m2==m1: + raise Exception("Smart Magnet has invalid detection.") + return m2 + + def set_supress(self, value): + smc_sup_det.write(value) + + def get_supress(self): + return smc_sup_det.read() + + def check_mounted(self, idle_time =1.0, timeout = -1, interval = 0.01): + self.assert_status() + start = time.time() + last = None + while True: + try: + det = self.is_mounted() + except: + det = None + if det != last: + settling_timestamp = time.time() + last = det + else: + if det is not None: + if (time.time()-settling_timestamp > idle_time): + return det + if timeout >= 0: + if (time.time() - start) > timeout: + raise Exception("Timeout waiting for Smart Magnet detection.") + time.sleep(interval) + + + def doUpdate(self): + try: + if self.get_supress(): + self.setState(State.Paused) + elif self.is_mounted(): + self.setState(State.Busy) + else: + self.setState(State.Ready) + except: + self.setState(State.Fault) + + def set_holding_current(self): + self.set_current(self.config.getFieldValue("holdingCurrent")) + + def set_resting_current(self): + self.set_current(self.config.getFieldValue("restingCurrent")) + + def set_mount_current(self): + self.set_current(self.config.getFieldValue("mountCurrent")) + + def set_unmount_current(self): + self.set_current(self.config.getFieldValue("unmountCurrent")) + + def set_reverse_current(self): + self.set_current(self.config.getFieldValue("reverseCurrent")) + + def set_default_current(self): + if self.is_mounted(): + self.set_holding_current() + else: + self.set_resting_current() + + def is_resting_current(self): + is_resting = 2.0 > abs( float(self.get_current()) - float(self.config.getFieldValue("restingCurrent")) ) + return is_resting + + + def apply_reverse(self): + reverse_wait = float(self.config.getFieldValue("reverseTime")) + if reverse_wait >0: + self.set_reverse_current() + time.sleep(reverse_wait) + + #Setting resting current to better detect sample + def apply_resting(self): + if not self.is_resting_current(): + self.set_resting_current() + + + + +add_device(SmartMagnet("smart_magnet"), force = True) + +smart_magnet.polling = 1000 + +smart_magnet.set_default_current() diff --git a/script/devices/Wago.py b/script/devices/Wago.py new file mode 100644 index 0000000..9c76bec --- /dev/null +++ b/script/devices/Wago.py @@ -0,0 +1,141 @@ +LED_LEVEL_ROOM_TEMPERATURE = 0.4 +LED_LEVEL_LN2 = 1.0 + + +################################################################################################### +# Leds +################################################################################################### + +def set_led_level(level): + level = max(min(float(level),100.0),0.0) + set_setting("led_level", level) + led_ctrl_1.write(led_ctrl_1.config.maxValue * level / 100.0) + led_ctrl_2.write(led_ctrl_2.config.maxValue * level / 100.0) + led_ctrl_3.write(led_ctrl_3.config.maxValue * level / 100.0) + +def get_led_level(): + level = get_setting("led_level") + return float(0 if level is None else level) + +def set_led_state(value): + """ + Turn leds on and off + """ + if value: + set_led_level(100.0) + else: + set_led_level(0.0) + +def get_led_state(): + """ + Returns led state (on/off) + """ + return led_ctrl_1.read() > 0 + +#TODO: The range should be set automatically reading LN2 sensor. +def set_led_range(room_temp = True): + """ + Led range should be limitted in room temperature + """ + max_val = LED_LEVEL_ROOM_TEMPERATURE if room_temp else LED_LEVEL_LN2 + led_ctrl_1.config.maxValue = max_val + led_ctrl_1.config.save() + led_ctrl_2.config.maxValue = max_val + led_ctrl_2.config.save() + led_ctrl_3.config.maxValue = max_val + led_ctrl_3.config.save() + led_ctrl_1.initialize() + led_ctrl_2.initialize() + led_ctrl_3.initialize() + if led_ctrl_1.read() > max_val: + led_ctrl_1.write(max_val) + if led_ctrl_2.read() > max_val: + led_ctrl_2.write(max_val) + if led_ctrl_3.read() > max_val: + led_ctrl_3.write(max_val) + set_led_level(get_led_level()) + + +def is_led_room_temp(): + return led_ctrl_1.config.maxValue <= LED_LEVEL_ROOM_TEMPERATURE + + + + +################################################################################################### +# Safety release +################################################################################################### + +def release_local(): + """ + Release local safety + """ + release_local_safety.write(False) + time.sleep(0.01) + release_local_safety.write(True) + time.sleep(0.01) + release_local_safety.write(False) + +def release_psys(): + """ + Release psys safety + """ + if is_manual_mode(): + raise Exception ("Cannot release PSYS in manual mode") + release_psys_safety.write(False) + time.sleep(0.01) + release_psys_safety.write(True) + time.sleep(0.01) + release_psys_safety.write(False) + + + +################################################################################################### +# Drier +################################################################################################### +MAX_HEATER_TIME = 70000 + +def set_air_stream(state): + """ + """ + valve_1.write(state) + valve_2.write(not state) + + +set_heater_chrono = None + +def monitor_heater_time(): + time.sleep(0.5) + try: + while get_heater(): + if set_heater_chrono.isTimeout(MAX_HEATER_TIME): + set_heater(False) + log("Heater timeout expired: turned off", False) + return + time.sleep(0.1) + except: + print sys.exc_info() + + +def get_heater(): + """ + """ + return gripper_dryer.read() + + +def set_heater(state): + """ + """ + global set_heater_chrono + if get_heater() != state: + gripper_dryer.write(state) + if state: + set_heater_chrono = Chrono() + fork(monitor_heater_time) + + +def get_air_stream(): + """ + """ + return valve_1.read() + diff --git a/script/hexiposi_positon.scd b/script/hexiposi_positon.scd new file mode 100644 index 0000000..471fb41 --- /dev/null +++ b/script/hexiposi_positon.scd @@ -0,0 +1,11 @@ +[ + [ [ true, "hexiposi_position", "Device", 1, 1, null ] ], + [ [ "1", null, null, null, null, null, null, null ], + [ "2", null, null, null, null, null, null, null ], + [ "3", null, null, null, null, null, null, null ], + [ "4", null, null, null, null, null, null, null ], + [ "5", null, null, null, null, null, null, null ] ], + [ [ ] ], + [ [ "", 1000, 100 ], + [ "", "" ] ] +] \ No newline at end of file diff --git a/script/imgproc/CameraCalibration.py b/script/imgproc/CameraCalibration.py new file mode 100644 index 0000000..07b123c --- /dev/null +++ b/script/imgproc/CameraCalibration.py @@ -0,0 +1,155 @@ +import ch.psi.pshell.device.Camera as Camera +import ch.psi.pshell.imaging.RendererMode as RendererMode +import ch.psi.pshell.imaging.Calibration as Calibration +from ch.psi.pshell.imaging.Overlays import * +import ch.psi.utils.swing.SwingUtils as SwingUtils +import javax.swing.SwingUtilities as SwingUtilities +from swingutils.threads.swing import callSwing +#SIMULATION = ch.psi.pshell.imaging.FileSource +""" +img.camera.setColorMode(Camera.ColorMode.Mono) +img.camera.setDataType(Camera.DataType.UInt8) +img.camera.setGrabMode(Camera.GrabMode.Continuous) +img.camera.setTriggerMode(Camera.TriggerMode.Fixed_Rate) +img.camera.setExposure(50.00) +img.camera.setAcquirePeriod(200.00) +img.camera.setGain(0.0) +img.config.rotationCrop=True +""" + +MOVE_HEXIPOSI = True +ROTATION_OFFSET = 180.0 + +if MOVE_HEXIPOSI: + release_safety() #enable_motion() + +sensor_width,sensor_height = img.camera.getSensorSize() +img.camera.setROI(0, 0,sensor_width, sensor_height) +img.config.rotation=0 +img.config.roiX,img.config.roiY, img.config.roiWidth,img.config.roiHeight =0,0,-1,-1 +img.config.setCalibration(None) +img.camera.stop() +img.camera.start() + + +p = show_panel(img) +dlg = SwingUtilities.getWindowAncestor(p) +dlg.setSize(800,800) +frm=SwingUtils.getFrame(p) +dlg.setLocationRelativeTo(frm) + +p.setMode(RendererMode.Fit) +ov_text = Text(Pen(java.awt.Color.GREEN.darker()), "", java.awt.Font("Verdana", java.awt.Font.PLAIN, 24), java.awt.Point(20,20)) +ov_text.setFixed(True) +p.addOverlay(ov_text) + + +try: + #Find image center and Prosilica ROI + ov_text.update("Click on the center of the Dewar...") + p.refresh() + dc = p.waitClick(60000) + print dc + width, height = min(dc.x, sensor_width-dc.x)*2, min(dc.y, sensor_height-dc.y)*2 + width, height = width - width%16, height - height%16 + width, height = min(width,1000), min(height,1000) + print width, height + roi_x = int(dc.x- width/2) + roi_y = int(dc.y- height/2) + roi_w = int(width) + roi_h = int(height) + set_setting("roi_x", roi_x) + set_setting("roi_y", roi_y) + set_setting("roi_w", roi_w) + set_setting("roi_h", roi_h) + img.camera.setROI(roi_x, roi_y, width, height) +except: + img.camera.setROI(int(get_setting("roi_x")), int(get_setting("roi_y")), int(get_setting("roi_w")), int(get_setting("roi_h"))) +finally: + img.camera.stop() + img.camera.start() + + +#Configure source +CC4 = (-129.9, -150) +CD5 = (129.9, -150) +CA5 = (-129.9, 150) +CF4 = (129.9, 150) + +DX = 259.8 +DY = 300.0 + +ROI_X = 470.0 +ROI_Y = 470.0 + +def rotate(x,y, degrees): + rotation = math.radians(degrees) + rw, rh = img.getImage().getWidth(), img.getImage().getHeight() + ox, oy = x - (rw / 2), y - (rh / 2) + x = ox * math.cos(rotation) - oy * math.sin(rotation) + rw / 2; + y = oy * math.cos(rotation) + ox * math.sin(rotation) + rh / 2; + return x,y + + +set_led_state(True) +try: + if MOVE_HEXIPOSI: set_hexiposi("C") + ov_text.update("Click on the center of C4 (19) position...") + p.refresh() + pc4 = p.waitClick(60000) + print pc4 + if MOVE_HEXIPOSI: set_hexiposi("D") + ov_text.update("Click on the center of D5 (13) position...") + p.refresh() + pd5 = p.waitClick(60000) + print pd5 + if MOVE_HEXIPOSI: set_hexiposi("F") + ov_text.update("Click on the center of F4 (04) position...") + p.refresh() + pf4 = p.waitClick(60000) + print pf4 + if MOVE_HEXIPOSI: set_hexiposi("A") + ov_text.update("Click on the center of A5 (28) position...") + p.refresh() + pa5 = p.waitClick(60000) + print pa5 + + + vc1x, vc1y, vc2x, vc2y = (pc4.x + pd5.x )/2.0, (pc4.y + pd5.y )/2.0, (pa5.x + pf4.x )/2.0, (pa5.y + pf4.y )/2.0 + hc1x, hc1y, hc2x, hc2y = (pc4.x + pa5.x )/2.0, (pc4.y + pa5.y )/2.0, (pd5.x + pf4.x )/2.0, (pd5.y + pf4.y )/2.0 + cx, cy = (vc1x + vc2x)/2, (hc1y + hc2y)/2 + + a1 = math.degrees(math.atan((cx-vc1x)/(vc1y-cy))) + a2 = math.degrees(math.atan((cx-vc2x)/(vc2y-cy))) + a = (a1+a2)/2 + + + dy = math.hypot(vc2y - vc1y, vc2x - vc1x) + dx = math.hypot(hc2x - hc1x, hc2y - hc1y) + print dy, dx, cx, cy + sx, sy = DX/dx, DY/dy + + + #Rotating center of puck + rcx, rcy = rotate(cx, cy, -a) + + + + roi_w, roi_h = int(ROI_X / sx), int(ROI_Y / sy) + roi_x, roi_y = int(rcx-roi_w/2), int(rcy-roi_h/2) + + print a, sx, sy, roi_w, roi_h + + img.config.rotation=-a + ROTATION_OFFSET + img.config.roiX,img.config.roiY, img.config.roiWidth,img.config.roiHeight = roi_x, roi_y, roi_w, roi_h + img.config.setCalibration(Calibration(sx, sy, -roi_w/2, -roi_h/2)) + img.config.save() + + set_return ("Success calibrating the camera") + +finally: + set_led_state(False) + p.removeOverlay(ov_text) + img.refresh() + + \ No newline at end of file diff --git a/script/imgproc/CoverDetection.py b/script/imgproc/CoverDetection.py new file mode 100644 index 0000000..904837a --- /dev/null +++ b/script/imgproc/CoverDetection.py @@ -0,0 +1,98 @@ +################################################################################################### +# Procedure to detect the cover orientation +################################################################################################### +assert_imaging_enabled() + + +#Parameters +FRAMES_INTEGRATION = 3 +STEP_SIZE = 2 +POSITION_NAMES = [ 'A','B','C','D', 'E', 'F'] + +#POSITION_ANGLES = [ 330, 30, 90, 150, 210, 270 ] +POSITION_ANGLES = [ 0, 60, 120, 180, 240, 300 ] +POSITION_TOLERANCE = 3 +MINIMUM_CONFIDENCE = 3 +DEBUG = cover_detection_debug +#REFERENCE_IMG = "ref2" +REFERENCE_IMG = "ref1" +BORDER = 7 + +#Load reference image +ref = load_image(str("{images}/cover/" + REFERENCE_IMG + ".png") , title="Line") + +#Pre-process camera image +#ip = load_image("{images}/cover/Cover_000" + str(index) + ".png", title="Img") +ip = integrate_frames(FRAMES_INTEGRATION) +ip = grayscale(ip, True) +smooth(ip) +#bandpass_filter(ip, 30, 1000) +edges(ip) +auto_threshold(ip, method = "MaxEntropy") +#binary_erode(ip, True) +#binary_dilate(ip, True) +ip.getProcessor().erode(1, 255) +cx,cy = int(ip.width/2), int(ip.height/2) +ip = sub_image(ip, cx-ref.width/2, cy-ref.height/2, ref.width, ref.height) + +if BORDER>0: + sip = sub_image(ip, BORDER,BORDER, ref.width-2*BORDER, ref.height-2*BORDER) + ip = pad_image(sip, BORDER, BORDER, BORDER, BORDER, fill_color=Color.WHITE) + +#Show ROI of pre-processed image +if DEBUG: + image_panel = show_panel(ip.bufferedImage) + + +#Calculate correlation between image and reference, rotating the reference from 0 to 360 +import ch.psi.pshell.imaging.Utils.integrateVertically as integrateVertically +ydata = [] +xdata = range (0,360,STEP_SIZE) +for i in xdata: + r = ref.duplicate() + r.getProcessor().setBackgroundValue(0.0) + r.getProcessor().rotate(float(i)) + op = op_fft(r, ip, "correlate") + bi = op.getBufferedImage() + p = integrateVertically(bi) + ydata.append(sum(p)) + + +#Calculate angle of the highest correlation, and confidence level +peaks = estimate_peak_indexes(ydata, xdata, (min(ydata) + max(ydata))/2, 25.0) +peaks_x = map(lambda x:xdata[x], peaks) +peaks_y = map(lambda x:ydata[x], peaks) +if len(peaks_x) > 1: + #remoce close peaks between 350 deg and 10 deg + if ((peaks_x[0]<10) and (peaks_x[1]>350)) or ((peaks_x[1]<10) and (peaks_x[0]>350)): + peaks.pop(1) + peaks_x.pop(1) + peaks_y.pop(1) + + +confidence = None if len(peaks_x)<2 else int(((float(peaks_y[0])/peaks_y[1])-1) * 1000) +angle = (None if len(peaks_x)==0 else peaks_x[0]) + +#From angle and confidence level estimate hexiposi position +position = None +if angle is not None: + for i in range(len(POSITION_NAMES)): + if abs(POSITION_ANGLES[i] - angle) <= POSITION_TOLERANCE: + position = POSITION_NAMES[i] + +#Plot the correlations values agains angle +if DEBUG: + plot(ydata, xdata=xdata) + +#Output results +if DEBUG: + print "Peaks", peaks + print "Peak indexes: " + str(peaks_x) + print "Peak values: " + str(peaks_y) + print "Angle: " , angle + print "Position: " , position + print "Confidence: " , confidence + +#Set return value +set_return ([position, angle, confidence]) + diff --git a/script/imgproc/CoverDetectionCalibration.py b/script/imgproc/CoverDetectionCalibration.py new file mode 100644 index 0000000..36f6a54 --- /dev/null +++ b/script/imgproc/CoverDetectionCalibration.py @@ -0,0 +1,40 @@ +#Parameters +FRAMES_INTEGRATION = 3 +MINIMUM_CONFIDENCE = 10 +DEBUG = cover_detection_debug +REFERENCE_IMG = "ref1" +ERODE_ITERATIONS = 2 + +#Load reference image +SIZE = [128,128] +BORDER = 7 + +hexiposi.move("A") +#Pre-process camera image +#ip = load_image("{images}/cover/Cover_000" + str(index) + ".png", title="Img") +ip = integrate_frames(FRAMES_INTEGRATION) +ip = grayscale(ip, True) +smooth(ip) +#bandpass_filter(ip, 30, 1000) +edges(ip) + +auto_threshold(ip, method = "MaxEntropy") +#binary_dilate(ip, True, 2) +for i in range(ERODE_ITERATIONS): + ip.getProcessor().erode(1, 255) + +cx,cy = int(ip.width/2), int(ip.height/2) +ip = sub_image(ip, cx-SIZE[0]/2, cy-SIZE[1]/2, SIZE[0], SIZE[1]) + +invert(ip) +ip = grayscale(ip, True) +#smooth(ip) + +if BORDER > 0: + sip = sub_image(ip, BORDER,BORDER, SIZE[0]-2*BORDER, SIZE[1]-2*BORDER) + ip = pad_image(sip, BORDER, BORDER, BORDER, BORDER) +if DEBUG: + image_panel = show_panel(ip.bufferedImage) + +save_image(ip, str("{images}/cover/" + REFERENCE_IMG + ".png") ,"png") + \ No newline at end of file diff --git a/script/imgproc/CreateMask.py b/script/imgproc/CreateMask.py new file mode 100644 index 0000000..98b3498 --- /dev/null +++ b/script/imgproc/CreateMask.py @@ -0,0 +1,29 @@ + +mask_img = new_image(img.getOutput().getWidth(), img.getOutput().getHeight(), image_type="byte", title = "mask_img", fill_color = Color.BLACK) + +mask_radius = 14 +mask_points = [] + + +def to_img_coords(absolute_coords): + return [img.getCalibration().convertToImageX(absolute_coords[0]), img.getCalibration().convertToImageY(absolute_coords[1])] + +for p in _puck_list: + mask_points.append(to_img_coords(p.led_mini)) + mask_points.append(to_img_coords(p.led_uni)) + + + +i = mask_img.getBufferedImage() +for p in mask_points: + #i.setRGB(p[0], p[1], 0xFFFFFF) + for x in range (p[0]-mask_radius, p[0]+mask_radius): + for y in range (p[1]-mask_radius, p[1]+mask_radius): + if math.hypot(x-p[0], y-p[1]) <= mask_radius: + i.setRGB(x,y, 0xFFFFFF) + + +mask_img = load_image(i) +#show_panel( mask_img.getBufferedImage()) + +set_return(mask_img) \ No newline at end of file diff --git a/script/imgproc/LedDetectionFilter.py b/script/imgproc/LedDetectionFilter.py new file mode 100644 index 0000000..a4818d8 --- /dev/null +++ b/script/imgproc/LedDetectionFilter.py @@ -0,0 +1,102 @@ +################################################################################################### +# Example of using ImageJ functionalities through ijutils. +################################################################################################### + +import datetime +from ijutils import * +import java.awt.Color as Color + +import ch.psi.pshell.imaging.Filter as Filter +from ch.psi.pshell.imaging.Overlays import * +import ch.psi.pshell.imaging.Pen as Pen + + +integration_count = 10 +integration_continuous = False +integration_partial = False +frames = [] +roi = get_roi() + + +color_roi = Color(0, 128, 0) + +renderer = show_panel(img) +renderer.clearOverlays() +ov_roi_shape = Ellipse(Pen(color_roi, 0,), java.awt.Point(roi[0], roi[1]), java.awt.Dimension(roi[2], roi[3])) +ov_roi_bound = Rect(Pen(color_roi, 0, Pen.LineStyle.dotted), java.awt.Point(roi[0], roi[1]), java.awt.Dimension(roi[2], roi[3])) +ov_roi_center = Crosshairs(Pen(color_roi, 0), java.awt.Point(roi_center[0],roi_center[1]), java.awt.Dimension(15,15)) + +renderer.addOverlays([ov_roi_shape, ov_roi_bound,ov_roi_center]) + + + + +last_ret = (None, None) +def detect_led(ip): + roi = get_roi() + global roi_center, roi_radius, integration_count, integration_continuous, integration_partial, frames + global count , last_ret + aux = sub_image(ip, roi[0], roi[1], roi[2], roi[3]) + grayscale(aux) + #gaussian_blur(aux) + if (integration_count>1): + frames.append(aux) + if len(frames) >integration_count: + del frames[0] + if not integration_continuous: + if (len(frames)< integration_count): + if last_ret[1] is not None: invert(last_ret[1]) + return last_ret + if (not integration_partial) and len(frames) <integration_count: + return last_ret + aux = integrate(frames) + + #aux = get_channel(aux, "blue") + invert(aux) + #subtract_background(aux) + #Tested ok: Huang, Mean, MaxEntropy, Percentile, Triangle, Yen + auto_threshold(aux, method = "Percentile") + #binary_open(aux) + (results,output) = analyse_particles(aux, 250,1000, + fill_holes = True, exclude_edges = False, print_table=False, + output_image = "outlines", minCirc = 0.3 + , maxCirc = 1.0) + r=results + + + points = "" + npoints = 0 + for row in range (r.counter): + if in_roi(r.getValue("XM",row), r.getValue("YM",row)): + points = points + " (" + str(int(r.getValue("XM", row))+roi[0]) + ", " + str(int(r.getValue("YM", row))+roi[1]) + ")" + npoints = npoints + 1 + print str(npoints) + " - " + points + + last_ret = (results,output) + if not integration_continuous: + frames = [] + + #if npoints!=12: + # save_image(op_image(aux, output,"xor", in_place=False), "{images}/" + str(datetime.datetime.now().strftime("%Y%m%d_%H%M%S"))+".png", "png") + #return (results,aux) + return (results,output) + + + + +ip = None + +class MyFilter(Filter): + def process(self, image, data): + global roi_center, roi_radius, ip + ip = load_image(image) + (results,output) = detect_led(ip) + if output is not None: + invert(output) + output = pad_image(output, roi[0], 0,roi[1], 0) + op_image(ip, output, "xor") + return ip.getBufferedImage() + +#Setting the filter to a source +img.setFilter(MyFilter()) + diff --git a/script/imgproc/LedDetectionProc.py b/script/imgproc/LedDetectionProc.py new file mode 100644 index 0000000..c01673d --- /dev/null +++ b/script/imgproc/LedDetectionProc.py @@ -0,0 +1,106 @@ +################################################################################################### +# Procedure to detect the puck light spots. +################################################################################################### +assert_imaging_enabled() + + +COVER_PRESENT = True +ROOM_TEMP = is_room_temp() +USE_MASK = True + +if get_exec_pars().source == CommandSource.ui: + PLOT = None + RENDERER = None + TEXT = None + +if COVER_PRESENT: + cover_position = hexiposi.readback.take() + if (cover_position is None) or (cover_position == "Unknown"): + raise Exception("Unknown cover position") + else: + block_id = cover_position.upper()[0] +else: + block_id = None +print "Block id: ", block_id + + + +number_frames = 5 if ROOM_TEMP else 10 +number_backgrounds = 5 if ROOM_TEMP else 5 +minimum_size = 78 # r = 5 # 150 +maximum_size = 750 # r = 15 #1500 +min_circ = 0.2 + +threshold_method = "MaxEntropy" if ROOM_TEMP else "Default" #Apparently good for LN2: Default, Intermodes, IsoData, Otsu +threshold_method,threshold_range = "Manual", (0, 215) + +exclude_edges = True +led_latency = 0.5 #0.1 + + + +set_led_state(False) +time.sleep(led_latency) +img.waitNext(2000) + +background = average_frames(number_backgrounds) +#background = integrate_frames(number_backgrounds) + +set_led_state(True) +time.sleep(led_latency) +img.waitNext(2000) +image = average_frames(number_frames) +#image = integrate_frames(number_frames) + +set_led_state(False) + +op_image(image, background, "subtract", float_result=True, in_place=True) +image=grayscale(image) + +if RENDERER is not None and RENDERER.isShowing(): + RENDERER.setImage(None, image.getBufferedImage(), None) +else: + RENDERER = show_panel(image.getBufferedImage()) +RENDERER.clearOverlays() + +if USE_MASK: + mask_img = run("imgproc/CreateMask") + #mask_img=grayscale(mask_img) + #show_panel( mask_img.getBufferedImage()) + op_image(image, mask_img, "and", float_result=False, in_place=True) + RENDERER.setImage(None, image.getBufferedImage(), None) + +invert(image) +if threshold_method == "Manual": + threshold(image, threshold_range[0], threshold_range[1]) +else: + auto_threshold(image, method = threshold_method) #Tested ok: MaxEntropy, Triangle, Yen +(r,output) = analyse_particles(image, minimum_size,maximum_size, + fill_holes = True, exclude_edges = exclude_edges, print_table=False, + output_image = "outlines", minCirc = min_circ + , maxCirc = 1.0) + +points = [] +for row in range (r.counter): + if in_roi(r.getValue("XM",row), r.getValue("YM",row)): + x, y = int(r.getValue("XM", row)), int(r.getValue("YM", row)) + cx, cy = img.getCalibration().convertToAbsoluteX(x), img.getCalibration().convertToAbsoluteY(y) + points.append([cx,cy]) + if RENDERER is not None: + RENDERER.addOverlay(Crosshairs(Pen(java.awt.Color.MAGENTA), java.awt.Point(x,y), java.awt.Dimension(15,15))) + + +clear_detection(block_id) +detect_pucks(points, block_id) +if PLOT is not None: + plot_base_plate(points, p=PLOT) + +ret = get_puck_detection_dict(block_id) + + +if TEXT is not None: + TEXT.setText(str(ret)) + + +set_return(ret) + diff --git a/script/imgproc/Utils.py b/script/imgproc/Utils.py new file mode 100644 index 0000000..addc508 --- /dev/null +++ b/script/imgproc/Utils.py @@ -0,0 +1,113 @@ + +################################################################################################### +# Image processing utilities +################################################################################################### + + +from ijutils import * +from ch.psi.pshell.imaging.Overlays import * +import ch.psi.pshell.imaging.Pen as Pen +import java.awt.Rectangle as Rectangle + +def get_img_cover_pos(): + [position, angle, confidence] = run("imgproc/CoverDetection") + return position + +def assert_img_in_cover_pos(pos = None): + if pos==None: + pos = hexiposi.take() + elif type(pos) is int: + pos = chr( ord('A') + (pos-1)) + elif is_string(pos): + pos = pos.upper() + img_segment = get_img_cover_pos() + if img_segment != pos: + raise Exception ("Image detection of cover does not match position: " + str(img_segment)) + + +def in_roi(x,y): + global roi_center, roi_radius, roi_border + return math.hypot(x-roi_center[0], y-roi_center[1]) < (roi_radius-roi_border) + + +def integrate(ips): + roi = get_roi() + aux = None + for i in range(len(ips)): + if i==0: + aux = new_image(roi[2], roi[3], image_type="float", title = "sum", fill_color = None) + op_image(aux, ips[i], "add", float_result=True, in_place=True) + return aux + +def average (ips): + aux = integrate(ips) + op_const(aux, "divide", len(ips), in_place=True) + return aux + +def grab_frames(samples): + frames = [] + for i in range(samples): + aux = get_image() + frames.append(aux) + return frames + +def average_frames(samples = 1): + return average(grab_frames(samples)) + +def integrate_frames(samples = 1): + return integrate(grab_frames(samples)) + + +roi_center = (600, 600) #(800, 600) +roi_radius = 600 +roi_border = 30 + +def get_roi(): + #roi_center = (img.output.width/2, img.output.height/2) + #roi_radius = min(roi_center[0], roi_center[1]) + #return (roi_center[0] - roi_radius, roi_center[1] - roi_radius, 2* roi_radius, 2*roi_radius) + global roi_center, roi_radius + roi_center = (img.output.width/2, img.output.height/2) + roi_radius = min(roi_center[0], roi_center[1]) + return (0,0,img.output.width, img.output.height) + +def get_image(): + roi = get_roi() + #ip = load_image(img.output) + #ret = ip if (roi is None) else sub_image(ip, roi[0], roi[1], roi[2], roi[3]) + #grayscale(ret, do_scaling=True) + + ret = load_image(Utils.grayscale(img.output, Rectangle(roi[0], roi[1], roi[2], roi[3]) if (roi is not None) else None)) + return ret + +#def detect_pucks(ip): +# """ +# """ +# aux = grayscale(ip, in_place=False) +# threshold(aux,0,50) +# binary_fill_holes(aux) +# return analyse_particles(aux, 10000,50000, +# fill_holes = False, exclude_edges = True,print_table=True, +# output_image = "outlines", minCirc = 0.4, maxCirc = 1.0) +# +#def detect_samples(ip): +# """ +# """ +# aux = grayscale(ip, in_place=False) +# invert(aux) +# subtract_background(aux) +# auto_threshold(aux) +# binary_open(aux) +# return analyse_particles(aux, 250,1000, +# fill_holes = False, exclude_edges = True,print_table=True, + + +r,g,b = [0]*256,[0]*256,[0]*256 +b[0]=0xFF +b[1]=0xFF ; g[1] = 0x80; r[1] = 0x80 +outline_lut1 = (r,g,b) + +r,g,b = [0]*256,[0]*256,[0]*256 +g[0]=0x80;r[0]=0x80; +g[1]=0xFF ; r[1] = 0x80; b[1] = 0x80 +outline_lut2 = (r,g,b) diff --git a/script/local.groovy b/script/local.groovy new file mode 100644 index 0000000..6cd1527 --- /dev/null +++ b/script/local.groovy @@ -0,0 +1,3 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Deployment specific global definitions - executed after startup.groovy +/////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/script/local.js b/script/local.js new file mode 100644 index 0000000..17db863 --- /dev/null +++ b/script/local.js @@ -0,0 +1,4 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////// +// Deployment specific global definitions - executed after startup.js +/////////////////////////////////////////////////////////////////////////////////////////////////// + diff --git a/script/local.py b/script/local.py new file mode 100644 index 0000000..02cae42 --- /dev/null +++ b/script/local.py @@ -0,0 +1,413 @@ +################################################################################################### +# Deployment specific global definitions - executed after startup.py +################################################################################################### +import traceback +from ch.psi.pshell.serial import TcpDevice +from ch.psi.pshell.modbus import ModbusTCP +import ch.psi.mxsc.Controller as Controller +import ch.psi.pshell.core.Nameable as Nameable +import ch.psi.utils.Chrono as Chrono +import ch.psi.mxsc.Controller as Controller + + + +run("setup/Layout") + + + +################################################################################################### +# Configuration +################################################################################################### + +IMAGING_ENABLED_PREFERENCE = "imaging_enabled" +PUCK_TYPES_PREFERENCE = "puck_types" +BARCODE_READER_SCAN_PUCKS = "barcode_reader_scan_pucks" +ROOM_TEMPERATURE_ENABLED_PREFERENCE = "room_temperature_enabled" +BEAMLINE_STATUS_ENABLED_PREFERENCE = "beamline_status_enabled" + +def is_imaging_enabled(): + setting = get_setting(IMAGING_ENABLED_PREFERENCE) + return not (str(setting).lower() == 'false') + +def set_imaging_enabled(value): + set_setting(IMAGING_ENABLED_PREFERENCE, (True if value else False) ) + +def assert_imaging_enabled(): + if is_imaging_enabled() == False: + raise Exception ("Imaging is disabled") + +#"unipuck", "minispine" or "mixed" +def set_puck_types(value): + set_setting(PUCK_TYPES_PREFERENCE, True if value else False ) + +def get_puck_types(): + setting = get_setting(PUCK_TYPES_PREFERENCE) + if setting == "unipuck" or setting == "minispine": + return setting + return "mixed" + + +def is_barcode_reader_scan_pucks(): + setting = get_setting(BARCODE_READER_SCAN_PUCKS) + return False if setting is None else setting.lower() == "true" + +def set_barcode_reader_scan_pucks(value): + set_setting(BARCODE_READER_SCAN_PUCKS, True if value else False ) + +def reset_mounted_sample_position(): + set_setting("mounted_sample_position", None) + + +def get_puck_barcode_reader(): + if is_barcode_reader_scan_pucks(): + return barcode_reader + else: + return barcode_reader_puck + +#In order to apply current config +set_imaging_enabled(is_imaging_enabled()) +set_puck_types(get_puck_types()) +set_barcode_reader_scan_pucks(is_barcode_reader_scan_pucks()) + + +force_dry_mount_count = get_setting("force_dry_mount_count") +if force_dry_mount_count is None: + set_setting("force_dry_mount_count", 0) + +force_dry_timeout = get_setting("force_dry_timeout") +if force_dry_timeout is None: + set_setting("force_dry_timeout", 0) + + + +def is_room_temperature_enabled(): + setting = get_setting(ROOM_TEMPERATURE_ENABLED_PREFERENCE) + return str(setting).lower() == 'true' + +set_setting(ROOM_TEMPERATURE_ENABLED_PREFERENCE, is_room_temperature_enabled()) + + +def is_beamline_status_enabled(): + setting = get_setting(BEAMLINE_STATUS_ENABLED_PREFERENCE) + return str(setting).lower() == 'true' + +set_setting(ROOM_TEMPERATURE_ENABLED_PREFERENCE, is_beamline_status_enabled()) + +################################################################################################### +# Scripted devices and pseudo-devices +################################################################################################### + +for script in ["devices/RobotSC", "devices/Wago", "devices/BarcodeReader", "devices/LaserDistance", \ + "devices/LedCtrl", "devices/SmartMagnet", "devices/HexiPosi", "devices/Gonio"]: + try: + run(script) + except: + print >> sys.stderr, traceback.format_exc() + +#if is_imaging_enabled(): +if get_device("img") is not None: + add_device(img.getContrast(), force = True) + add_device(img.getCamera(), force = True) + + +################################################################################################### +# Utility modules +################################################################################################### + +run("data/samples") +run("data/pucks") +run("motion/tools") +run("motion/mount") +run("motion/unmount") +run("motion/get_dewar") +run("motion/put_dewar") +run("motion/get_gonio") +run("motion/put_gonio") +run("motion/move_dewar") +run("motion/move_gonio") +run("motion/move_heater") +run("motion/move_home") +run("motion/move_park") +run("motion/move_cold") +run("motion/move_scanner") +run("motion/move_aux") +run("motion/get_aux") +run("motion/put_aux") +run("motion/dry") +run("motion/trash") +run("motion/homing_hexiposi") +run("motion/calibrate_tool") +run("motion/scan_pin") +run("motion/robot_recover") +run("motion/recover") +run("tools/Math") +if is_imaging_enabled(): + run("imgproc/Utils") + +def system_check(robot_move=True): + if not air_pressure_ok.read(): + raise Exception("Air pressure is not ok") + if not n2_pressure_ok.read(): + raise Exception("N2 pressure is not ok") + hexiposi.assert_in_known_position() + + if robot_move: + if not feedback_local_safety.read(): + raise Exception("Local safety not released") + auto = not is_manual_mode() + if auto: + if not feedback_psys_safety.read(): + raise Exception("Psys safety not released") + if not guiding_tool_park.read(): + raise Exception("Guiding tool not parked") + +def system_check_msg(): + try: + system_check(True) + return "Ok" + except: + return sys.exc_info()[1] + +def get_puck_dev(segment, puck): + if type(segment) is int: + segment = chr( ord('A') + (segment-1)) + + return Controller.getInstance().getPuck(str(segment).upper() + str(puck)) + +def get_puck_elect_detection(segment, puck): + return str(get_puck_dev(segment, puck).detection) + +def get_puck_img_detection(segment, puck): + return str(Controller.getInstance().getPuck(str(segment).upper() + str(puck)).imageDetection) + +def assert_puck_detected(segment, puck): + if (segment == AUX_SEGMENT) and (puck == 1): + return + if get_puck_elect_detection(segment, puck) != "Present": + raise Exception ("Puck " + str(segment).upper() + str(puck) + " not present") + + +def start_puck_detection(): + run("tools/RestartPuckDetection") + +def check_puck_detection(): + return run("tools/CheckPuckDetection") + +def stop_puck_detection(): + run("tools/StopPuckDetection") + + + +def get_detected_pucks(): + ret = [] + for i in range(30): + p = BasePlate.getPucks()[i] + if (str(p.getDetection()) == "Present"): + ret.append(str(p.getName())) + return ret + +def get_pucks_info(): + ret = [] + for i in range(30): + p = BasePlate.getPucks()[i] + name = p.getName() + det = str(p.getDetection()) + barcode = "" if p.getId() is None else p.getId() + + ret.append({"puckAddress": name, "puckState": det, "puckBarcode":barcode}) + return json.dumps(ret) + + +################################################################################################### +# Device initialization +################################################################################################### + +try: + set_heater(False) + set_air_stream(False) +except: + print >> sys.stderr, traceback.format_exc() + + +try: + release_local_safety.write(False) + release_psys_safety.write(False) +except: + print >> sys.stderr, traceback.format_exc() + +try: + hexiposi.polling=500 +except: + print >> sys.stderr, traceback.format_exc() + +try: + robot.setPolling(DEFAULT_ROBOT_POLLING) + robot.set_tool(TOOL_DEFAULT) + robot.set_frame(FRAME_DEFAULT) + robot.set_motors_enabled(True) + robot.set_joint_motors_enabled(True) +except: + print >> sys.stderr, traceback.format_exc() + +if is_imaging_enabled(): + try: + import ch.psi.pshell.device.Camera as Camera + #img.camera.setColorMode(Camera.ColorMode.Mono) + #img.camera.setDataType(Camera.DataType.UInt8) + img.camera.setGrabMode(Camera.GrabMode.Continuous) + img.camera.setTriggerMode(Camera.TriggerMode.Fixed_Rate) + img.camera.setExposure(25.00) + img.camera.setAcquirePeriod(200.00) + img.camera.setGain(0.0) + #img.camera.setROI(200, 0,1200,1200) + """ + img.camera.setROI(300, 200,1000,1000) + img.config.rotation=17 + img.config.rotationCrop=True + img.config.roiX,img.config.roiY, img.config.roiWidth,img.config.roiHeight = 50,50,900,900 + """ + img.camera.setROI(int(get_setting("roi_x")), int(get_setting("roi_y")), int(get_setting("roi_w")), int(get_setting("roi_h"))) + + img.camera.stop() + img.camera.start() + except: + print >> sys.stderr, traceback.format_exc() + +#TODO: The Smart Magnet keeps moving sample if detecting is enabled +# Detection keeps disabled unless during moount/unmount +try: + smart_magnet.set_supress(True) +except: + print >> sys.stderr, traceback.format_exc() + +#gripper_cam.paused = True +################################################################################################### +# Device monitoring +################################################################################################### + +DEWAR_LEVEL_RT = 5.0 +is_room_temperature = False + +def is_room_temp(): + return is_room_temperature + + +class DewarLevelListener (DeviceListener): + def onValueChanged(self, device, value, former): + global is_room_temperature + if value is not None: + is_room_temperature = value <= DEWAR_LEVEL_RT +dewar_level_listener = DewarLevelListener() + +for l in dewar_level.listeners: + #if isinstance(l, DewarLevelListener): #Class changes... + if Nameable.getShortClassName(l.getClass()) == "DewarLevelListener": + dewar_level.removeListener(l) + +dewar_level.addListener(dewar_level_listener) +dewar_level_listener.onValueChanged(dewar_level, dewar_level.take(), None) + + + + +class HexiposiListener (DeviceListener): + def onValueChanging(self, device, value, former): + robot.assert_cleared() + +hexiposi_listener = HexiposiListener() +hexiposi.addListener(hexiposi_listener) + +################################################################################################### +# Global variables & application state +################################################################################################### + + +context = get_context() + +cover_detection_debug = False + +in_mount_position = False + + +def assert_mount_position(): + print "Source: ", get_exec_pars().source + if not in_mount_position and get_exec_pars().source == CommandSource.server : + raise Exception("Not in mount position") + + +def is_puck_loading(): + return robot.state == State.Ready and robot.take()["pos"] == 'pPark' and \ + feedback_psys_safety.take() == False and \ + not guiding_tool_park.read() + +def set_pin_offset(val): + if abs(val) >5: + raise Exception("Invalid pin offset: " + str(val)) + try: + set_setting("pin_offset",float(val)) + except: + log("Error setting pin offset: " + str(sys.exc_info()[1]), False) + +def get_pin_offset(): + try: + ret = float(get_setting("pin_offset")) + if abs(ret) >5: + raise Exception("Invalid configured pin offset: " + str(ret)) + return ret + except: + log("Error getting pin offset: " + str(sys.exc_info()[1]), False) + return 0.0 + + +def set_pin_angle_offset(val): + if (abs(val) > 180.0) or (abs(val) < -180.0): + raise Exception("Invalid pin angle offset: " + str(val)) + try: + set_setting("pin_angle_offset",float(val)) + except: + log("Error setting pin angle offset: " + str(sys.exc_info()[1]), False) + +def get_pin_angle_offset(): + try: + ret = float(get_setting("pin_angle_offset")) + if (abs(ret) > 180.0) or (abs(ret) < -180.0): + raise Exception("Invalid configured pin angle offset: " + str(ret)) + return ret + except: + log("Error getting pin angle offset: " + str(sys.exc_info()[1]), False) + return 0.0 + +def is_force_dry(): + try: + dry_mount_counter = int(get_setting("dry_mount_counter")) + except: + dry_mount_counter = 0 + + try: + dry_timespan = time.time() - float( get_setting("dry_timestamp")) + except: + dry_timespan = 3600 + + try: + force_dry_mount_count = int(get_setting("force_dry_mount_count")) + if force_dry_mount_count>0 and dry_mount_counter>=force_dry_mount_count: + return True + except: + pass + + try: + force_dry_timeout = float(get_setting("force_dry_timeout")) + if force_dry_timeout>0 and dry_timespan>=force_dry_timeout: + return True + except: + pass + return False + + +update() +add_device(Controller.getInstance().basePlate, True) +restore_samples_info() + + +print "Initialization complete" + \ No newline at end of file diff --git a/script/motion/calibrate_tool.py b/script/motion/calibrate_tool.py new file mode 100644 index 0000000..5357ef0 --- /dev/null +++ b/script/motion/calibrate_tool.py @@ -0,0 +1,32 @@ +def calibrate_tool(): + """ + """ + print "calibrate_tool" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + (detected, dm) = move_scanner() + + if detected: + print "Pin detected, trashing..." + trash() + (detected, dm) = move_scanner() + if detected: + raise Exception("Cannot trash pin") + + robot.open_tool() + robot.get_calibration_tool() + + run("calibration/ToolCalibration3") + + robot.put_calibration_tool() + + robot.save_program() diff --git a/script/motion/dry.py b/script/motion/dry.py new file mode 100644 index 0000000..40b04bc --- /dev/null +++ b/script/motion/dry.py @@ -0,0 +1,48 @@ + + +def dry(heat_time=40.0, speed=0.4, wait_cold = 30.0): + """ + heat_time (float): in seconds + speed (float): % of nominal speed + wait_cold(float): if negative, move to dewar after drying + Else move to cold and wait (in seconds) before returning. + """ + print "dry" + + + if robot.simulated: + time.sleep(10.0) + return + + #Initial checs + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + set_status("Drying") + + #Enabling + enable_motion() + + try: + set_heater(True) + robot.move_heater(speed, False) + time.sleep(heat_time) + robot.move_heater(speed, True) + set_air_stream(True) + robot.move_heater(speed, False) + finally: + set_heater(False) + set_air_stream(False) + + + set_setting("dry_mount_counter", 0) + set_setting("dry_timestamp",time.time()) + + if wait_cold >=0 : + robot.move_cold() + time.sleep(wait_cold) + else: + robot.move_park() \ No newline at end of file diff --git a/script/motion/get_aux.py b/script/motion/get_aux.py new file mode 100644 index 0000000..67bfc7d --- /dev/null +++ b/script/motion/get_aux.py @@ -0,0 +1,21 @@ +def get_aux(sample): + """ + """ + print "get_aux: ",sample + + #Initial checks + assert_valid_sample(sample) + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + hexiposi.assert_homed() + + #Enabling + enable_motion() + + if not robot.is_aux(): + robot.move_aux() + + robot.get_aux(sample) diff --git a/script/motion/get_dewar.py b/script/motion/get_dewar.py new file mode 100644 index 0000000..d0559fc --- /dev/null +++ b/script/motion/get_dewar.py @@ -0,0 +1,30 @@ +def get_dewar(segment, puck, sample, force=False): + """ + """ + print "get_dewar: ", segment, puck, sample, force + + #Initial checks + assert_valid_address(segment, puck, sample) + assert_puck_detected(segment, puck) + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + hexiposi.assert_homed() + #location = robot.get_current_point() + + + #Enabling + enable_motion() + + set_hexiposi(segment) + + if not force: + visual_check_hexiposi(segment) + + if not robot.is_dewar(): + robot.move_dewar() + + robot.get_dewar(segment, puck, sample) diff --git a/script/motion/get_gonio.py b/script/motion/get_gonio.py new file mode 100644 index 0000000..2123e2a --- /dev/null +++ b/script/motion/get_gonio.py @@ -0,0 +1,20 @@ +def get_gonio(force=False): + """ + """ + print "get_gonio: ", force + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + + if not robot.is_gonio(): + robot.move_gonio() + + robot.get_gonio() diff --git a/script/motion/homing_hexiposi.py b/script/motion/homing_hexiposi.py new file mode 100644 index 0000000..5c99f9e --- /dev/null +++ b/script/motion/homing_hexiposi.py @@ -0,0 +1,18 @@ +def homing_hexiposi(): + """ + """ + print "homing_hexiposi" + + #Initial checks + robot.assert_no_task() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + #location = robot.get_current_point() + + set_status("Homing hexiposi") + hexiposi.move_home() + hexiposi.waitState(State.Ready,-1) + hexiposi.move_pos(1) + + \ No newline at end of file diff --git a/script/motion/mount.py b/script/motion/mount.py new file mode 100644 index 0000000..bf1056f --- /dev/null +++ b/script/motion/mount.py @@ -0,0 +1,134 @@ +mount_sample_id = None +mount_sample_detected = None + +def mount(segment, puck, sample, force=False, read_dm=False, auto_unmount=False): + """ + """ + global mount_sample_id, mount_sample_detected + print "mount: ", segment, puck, sample, force + + start = time.time() + + is_aux = (segment == AUX_SEGMENT) + needs_chilling = not is_aux and (not robot.is_cold()) + needs_drying = is_aux and robot.is_cold() + + puck_address = get_puck_address(puck) + if puck_address is None: + puck_obj = get_puck_obj_by_id(puck) + if puck_obj is not None: + puck_address = puck_obj.name + if puck_address is not None: + print "puck address: ", puck_address + segment = puck_address[:1] + puck = int(puck_address[1:]) + #Initial checks + assert_valid_address(segment, puck, sample) + assert_puck_detected(segment, puck) + + if robot.simulated: + time.sleep(3.0) + mount_sample_detected = True + mount_sample_id = "YYY0001" + update_samples_info_sample_mount(get_puck_name(segment, puck), sample, mount_sample_detected, mount_sample_id) + set_setting("mounted_sample_position", get_sample_name(segment, puck, sample)) + return [mount_sample_detected, mount_sample_id] + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + hexiposi.assert_homed() + assert_mount_position() + + + try: + if needs_chilling: + robot.move_cold() + time.sleep(30.0) + + if smart_magnet.get_supress() == True: + smart_magnet.set_supress(False) + time.sleep(0.2) + #To better dectect sample + smart_magnet.apply_resting() + time.sleep(0.5) + if smart_magnet.check_mounted(idle_time=0.25, timeout = 1.0) == True: + if auto_unmount and (get_setting("mounted_sample_position") is not None): + #auto_unmount set to true so detection remains enabled + unmount(force = True, auto_unmount = True) + else: + raise Exception("Pin detected on gonio") + set_status("Mounting: " + str(segment) + str(puck) + str(sample)) + #location = robot.get_current_point() + + #Enabling + enable_motion() + + if needs_drying: + dry(wait_cold=-1) + if is_aux: + if not robot.is_aux(): + robot.move_aux() + + robot.get_aux(sample) + + else: + set_hexiposi(segment) + + if not force: + visual_check_hexiposi(segment) + + if not robot.is_dewar(): + robot.move_dewar() + + robot.get_dewar(segment, puck, sample) + + + if read_dm: + barcode_reader.start_read(10.0) + robot.move_scanner() + #time.sleep(1.0) + + robot.move_gonio() + + if read_dm: + mount_sample_id = barcode_reader.get_readout() + print "Datamatrix: " , mount_sample_id + else: + mount_sample_id = None + + + robot.put_gonio() + + + try: + dry_mount_count = int(get_setting("dry_mount_counter")) + except: + dry_mount_count = 0 + set_setting("dry_mount_counter", dry_mount_count+1) + + if is_aux: + robot.move_home() + else: + robot.move_cold() + + mount_sample_detected = smart_magnet.check_mounted(idle_time=0.25, timeout = 1.0) + update_samples_info_sample_mount(get_puck_name(segment, puck), sample, mount_sample_detected, mount_sample_id) + if mount_sample_detected == False: + raise Exception("No pin detected on gonio") + + + if is_force_dry(): + smart_magnet.set_default_current() + print "Auto dry" + log("Starting auto dry", False) + set_exec_pars(then = "dry()") + + set_setting("mounted_sample_position", get_sample_name(segment, puck, sample)) + return [mount_sample_detected, mount_sample_id] + finally: + smart_magnet.set_default_current() + smart_magnet.set_supress(True) + diff --git a/script/motion/move_aux.py b/script/motion/move_aux.py new file mode 100644 index 0000000..94d6468 --- /dev/null +++ b/script/motion/move_aux.py @@ -0,0 +1,18 @@ +def move_aux(): + """ + """ + print "move_aux" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + + if not robot.is_aux(): + robot.move_aux() \ No newline at end of file diff --git a/script/motion/move_cold.py b/script/motion/move_cold.py new file mode 100644 index 0000000..89c8920 --- /dev/null +++ b/script/motion/move_cold.py @@ -0,0 +1,22 @@ +def move_cold(): + """ + """ + print "move_cold" + + if robot.simulated: + time.sleep(3.0) + return + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + + if not robot.is_cold(): + robot.move_cold() \ No newline at end of file diff --git a/script/motion/move_dewar.py b/script/motion/move_dewar.py new file mode 100644 index 0000000..3dfcbfe --- /dev/null +++ b/script/motion/move_dewar.py @@ -0,0 +1,18 @@ +def move_dewar(): + """ + """ + print "move_dewar" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + + if not robot.is_dewar(): + robot.move_dewar() \ No newline at end of file diff --git a/script/motion/move_gonio.py b/script/motion/move_gonio.py new file mode 100644 index 0000000..82397f9 --- /dev/null +++ b/script/motion/move_gonio.py @@ -0,0 +1,18 @@ +def move_gonio(): + """ + """ + print "move_gonio" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + + if not robot.is_gonio(): + robot.move_gonio() diff --git a/script/motion/move_heater.py b/script/motion/move_heater.py new file mode 100644 index 0000000..000e500 --- /dev/null +++ b/script/motion/move_heater.py @@ -0,0 +1,18 @@ +def move_heater(): + """ + """ + print "move_heater" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + + if not robot.is_heater(): + robot.move_heater() diff --git a/script/motion/move_home.py b/script/motion/move_home.py new file mode 100644 index 0000000..30592d6 --- /dev/null +++ b/script/motion/move_home.py @@ -0,0 +1,18 @@ +def move_home(): + """ + """ + print "move_home" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + + if not robot.is_home(): + robot.move_home() diff --git a/script/motion/move_park.py b/script/motion/move_park.py new file mode 100644 index 0000000..e1715c0 --- /dev/null +++ b/script/motion/move_park.py @@ -0,0 +1,18 @@ +def move_park(): + """ + """ + print "move_park" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + + if not robot.is_park(): + robot.move_park() \ No newline at end of file diff --git a/script/motion/move_scanner.py b/script/motion/move_scanner.py new file mode 100644 index 0000000..b8fe41f --- /dev/null +++ b/script/motion/move_scanner.py @@ -0,0 +1,30 @@ + +def move_scanner(): + """ + """ + print "move_scanner" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + barcode_reader.start_read(10.0) + if not robot.is_scanner(): + robot.move_scanner() + + time.sleep(0.25) + dm = barcode_reader.get_readout() + if dm is None: + detected = is_pin_detected_in_scanner() + else: + detected = True + + print ("Detected: " + str( detected) + " - Datamatrix: " + str(dm)) + + return (detected, dm) diff --git a/script/motion/put_aux.py b/script/motion/put_aux.py new file mode 100644 index 0000000..c41ee81 --- /dev/null +++ b/script/motion/put_aux.py @@ -0,0 +1,21 @@ +def put_aux(sample): + """ + """ + print "put_aux: ",sample + + #Initial checks + assert_valid_sample(sample) + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + hexiposi.assert_homed() + + #Enabling + enable_motion() + + if not robot.is_aux(): + robot.move_aux() + + robot.put_aux(sample) diff --git a/script/motion/put_dewar.py b/script/motion/put_dewar.py new file mode 100644 index 0000000..7d5c74d --- /dev/null +++ b/script/motion/put_dewar.py @@ -0,0 +1,30 @@ +def put_dewar(segment, puck, sample, force=False): + """ + """ + print "put_dewar: ", segment, puck, sample, force + + #Initial checks + assert_valid_address(segment, puck, sample) + assert_puck_detected(segment, puck) + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + hexiposi.assert_homed() + + #Enabling + enable_motion() + + set_hexiposi(segment) + + if not force: + visual_check_hexiposi(segment) + + #location = robot.get_current_point() + + if not robot.is_dewar(): + robot.move_dewar() + + robot.put_dewar(segment, puck, sample) diff --git a/script/motion/put_gonio.py b/script/motion/put_gonio.py new file mode 100644 index 0000000..c23463f --- /dev/null +++ b/script/motion/put_gonio.py @@ -0,0 +1,23 @@ +def put_gonio(force=False): + """ + """ + print "put_gonio: ", force + + + if robot.simulated: + time.sleep(3.0) + return + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + if not robot.is_gonio(): + robot.move_gonio() + robot.put_gonio() diff --git a/script/motion/recover.py b/script/motion/recover.py new file mode 100644 index 0000000..ff67e16 --- /dev/null +++ b/script/motion/recover.py @@ -0,0 +1,163 @@ +import org.apache.commons.math3.geometry.euclidean.threed.Segment as Segment +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D as Vector3D +import org.apache.commons.math3.geometry.euclidean.threed.Line as Line3D + +RECOVER_DESC = "mRecovery" +RECOVER_TOOL = TOOL_DEFAULT + +known_segments = [ ("pHome", "pPark", 50), \ + ("pHome", "pGonio", 30), \ + ("pHome", "pScan", 25), \ + ("pHome", "pHeater", 75), \ + ("pHome", "pDewar", 10), \ + ("pHome", "pHelium", 230), \ + ("pGonio", "pGonioG", 10), \ + ("pPark", "pHeat", 40), \ + ("pHeater", "pHeatB", 10), \ + ("pPark", "pAux", 50), \ + ] + + +def get_robot_position(): + return robot.get_cartesian_pos() + + +def get_dist_to_line(segment): + tolerance = segment[2] + p1, p2 = robot.get_pnt(segment[0]), robot.get_pnt(segment[1]) + p = get_robot_position() + v = Vector3D(p[0], p[1], p[2]) + v1 = Vector3D(p1[0], p1[1], p1[2]) + v2 = Vector3D(p2[0], p2[1], p2[2]) + l = Line3D(v1, v2, 0.01) + return l.distance(v) + +def get_dist_to_segment(segment): + tolerance = segment[2] + p1, p2 = robot.get_pnt(segment[0]), robot.get_pnt(segment[1]) + p = get_robot_position() + v = Vector3D(p[0], p[1], p[2]) + v1 = Vector3D(p1[0], p1[1], p1[2]) + v2 = Vector3D(p2[0], p2[1], p2[2]) + l = Line3D(v1, v2, 0.01) + d = l.distance(v) + + pj = get_projection_at_line(segment) + + d1, d2 = v1.distance(v), v2.distance(v) + dp1, dp2 = v1.distance(pj), v2.distance(pj) + d12 = v1.distance(v2) + + + if (dp1 + dp2) > (d12 + tolerance): + d = max(d,min(d1,d2)) + return d + +def is_on_segment(segment): + tolerance = segment[2] + d = get_dist_to_segment(segment) + + if d > tolerance: + #print "Current robot position " + str(p) + " not on segment " + str(segment) + " - distance=" + str(d) + return False + #print "Current robot position " + str(p) + " on segment " + str(segment) + " - distance=" + str(d) + return True + +def get_projection_at_line(segment): + tolerance = segment[2] + p1, p2 = robot.get_pnt(segment[0]), robot.get_pnt(segment[1]) + p = get_robot_position() + v = Vector3D(p[0], p[1], p[2]) + v1 = Vector3D(p1[0], p1[1], p1[2]) + v2 = Vector3D(p2[0], p2[1], p2[2]) + l = Line3D(v1, v2, 0.01) + a = l.getAbscissa(v) + lv = l.pointAt(a) + return lv + + +def get_current_segment(): + for segment in known_segments: + if is_on_segment(segment): + return segment + return None + +def get_current_distance(): + for segment in known_segments: + if is_on_segment(segment): + return get_dist_to_segment(segment) + return None + + +def move_to_segment(segment): + tolerance = segment[2] + p = get_robot_position() + v = Vector3D(p[0], p[1], p[2]) + lv = get_projection_at_line(segment) + dlv = lv.distance(v) + if dlv> (tolerance + 0.1): + raise Exception( "Error moving from " + str(p) + " to segment - distance=" + str(dlv)) + d = [lv.x, lv.y, lv.z, p[3], p[4], p[5]] + print "Moving from " + str(p) + " to segment " + str(segment) + " - distance=" + str(dlv) + " - dest=" + str(d) + + try: + robot.movel(d, tool=RECOVER_TOOL, desc=RECOVER_DESC, sync=True) + print "Done" + except: + print sys.exc_info()[1] + +#Moves to first point of the segment ehich is safer, unless in the vicinity of the second +def move_to_safest_point(segment, vicinity_tolerance = 100): + d1, d2 = robot.get_distance_to_pnt(segment[0]), robot.get_distance_to_pnt(segment[1]) + #Always moving to primary point + if False : #(d2<=d1) and (d2 <= vicinity_tolerance): + print "Moving to secondary point " + str(segment[1] + " - d1=" + str(d1) + " d2=" + str(d2) ) + robot.movel(segment[1], tool=RECOVER_TOOL, desc=RECOVER_DESC, sync=True) + else: + print "Moving to primary point " + str(segment[0] + " - d1=" + str(d1) + " d2=" + str(d2) ) + robot.movel(segment[0], tool=RECOVER_TOOL, desc=RECOVER_DESC, sync=True) + print "Done" + #print "Recovered to point " + str(robot.get_curjoint_or_pointrent_point()) + + +def recover(move_park = True): + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + + if robot.get_current_point() is not None: + raise Exception("Robot is in known location") + + set_status("Recovering") + + #Enabling + enable_motion() + + + is_on_known_segment = False + for segment in known_segments: + if is_on_segment(segment): + #try: + # robot.set_monitor_speed(5) + is_on_known_segment = True + move_to_segment(segment) + move_to_safest_point(segment) + location = robot.get_current_point() + if location is None: + raise Exception("Robot didn't reach known point") + print "Success recovered to point: " + str(location) + if move_park: + robot.move_park() + return "Success recovered to park position" + else: + return "Success recovered to point: " + str(location) + #finally: + # robot.set_default_speed() + if not is_on_known_segment: + raise Exception("Robot is not in known segment") + + + + + \ No newline at end of file diff --git a/script/motion/robot_recover.py b/script/motion/robot_recover.py new file mode 100644 index 0000000..c25d712 --- /dev/null +++ b/script/motion/robot_recover.py @@ -0,0 +1,16 @@ +def robot_recover(): + """ + """ + print "robot_recover" + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + + set_status("Recovering robot") + + #Enabling + enable_motion() + + robot.robot_recover() diff --git a/script/motion/scan_pin.py b/script/motion/scan_pin.py new file mode 100644 index 0000000..7683694 --- /dev/null +++ b/script/motion/scan_pin.py @@ -0,0 +1,94 @@ +def scan_pin(segment, puck, sample, force=False): + pin_name = get_sample_name(segment, puck, sample) + + print "scan pin", pin_name + #Initial checks + assert_valid_address(segment, puck, sample) + assert_puck_detected(segment, puck) + is_aux = (segment == AUX_SEGMENT) + + if robot.simulated: + time.sleep(0.5) + return "Present" + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + + set_status("Scanning pin: " + str(pin_name)) + + enable_motion() + + if is_aux: + if not robot.is_aux(): + robot.move_aux() + + robot.get_aux(sample) + else: + set_hexiposi(segment) + if not force: + visual_check_hexiposi(segment) + + if not robot.is_dewar(): + robot.move_dewar() + + robot.get_dewar(segment, puck, sample) + + (detected, dm) = move_scanner() + update_samples_info_sample_scan(get_puck_name(segment, puck), sample, detected, dm) + + if is_aux: + robot.move_aux() + robot.put_aux( sample) + else: + robot.move_dewar() + robot.put_dewar(segment, puck, sample) + ret = "Empty" + if detected: + if (dm is None) or (len(dm.strip())==0): + ret = "Present" + else: + ret = str(dm) + return ret + + +def scan_puck(segment, puck, force=False): + if segment == AUX_SEGMENT: + raise Exception("Cannot scan auxiliary puck") + ret = [] + for i in range(16): + ret.append(scan_pin (segment, puck, i+1, force)) + return ret + + +def scan_gripper(): + print "scan gripper" + #Initial checks + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + + set_status("Scanning gripper") + + enable_motion() + + (detected, dm) = move_scanner() + + robot.move_home() + + ret = "Empty" + if detected: + if (dm is None) or (len(dm.strip())==0): + ret = "Present" + else: + ret = str(dm) + return ret diff --git a/script/motion/tools.py b/script/motion/tools.py new file mode 100644 index 0000000..3cb76ef --- /dev/null +++ b/script/motion/tools.py @@ -0,0 +1,179 @@ +POSITION_TOLERANCE = 50 + + +def is_manual_mode(): + """ + return if operating in local mode. TODO: should be based on IO, not on robot flag. + """ + return robot.working_mode == "manual" + +def release_safety(): + """ + Release sefety signals acording to working mode + """ + if air_pressure_ok.take() != True: + raise Exception("Cannot release safety: air preassure not ok") + if n2_pressure_ok.take() != True: + raise Exception("Cannot release safety: n2 pressure not ok") + auto = not is_manual_mode() + if auto: + if feedback_psys_safety.read() == False: + release_psys() + time.sleep(0.5) + if feedback_psys_safety.read() == False: + raise Exception("Cannot enable power: check doors") + + if feedback_local_safety.read() == False: + release_local() + time.sleep(0.5) + if feedback_local_safety.read() == False: + raise Exception("Cannot enable power: check sample changer emergency stop button") + +def enable_motion(): + """ + Check safety and enable arm power if in remote mode + """ + release_safety() + system_check(robot_move=True) + auto = not is_manual_mode() + if auto: + if not robot.state.isNormal(): + raise Exception("Cannot enable power: robot state is " + str(robot.state)) + robot.enable() + +def set_hexiposi(pos, force = False): + """ + Set the hexiposi position in remote mode, or wait for it to be set in manual mode + """ + robot.assert_cleared() + if force == False: + if hexiposi.position == pos: + return + + if is_manual_mode(): + set_status("Move Hexiposi to position " + str(pos) + " ...") + try: + hexiposi.waitInPosition(pos, -1) + finally: + set_status(None) + else: + hexiposi.move(pos) + +#Can be used if cover has following error (no checking readback) +def _set_hexiposi(pos): + hexiposi.moveAsync(pos) + time.sleep(1.0) + hexiposi.waitReady(-1) + + +def visual_check_hexiposi(segment): + if is_imaging_enabled(): + #if is_manual_mode(): ? + if hexiposi.moved: + #Clearing for image processing + if not robot.is_park(): + print "Moving robot to park to clear camera view..." + robot.move_park() + assert_img_in_cover_pos(segment) + hexiposi.moved = False + + + +def wait_end_of_move(): + robot.update() + while (not robot.settled) or (not robot.empty) or (not robot.isReady()) : + time.sleep(0.01) + + +def move_to_home(): + #robot.reset_motion("jHome") + robot.movej("pHome", robot.tool , DESC_SCAN) + wait_end_of_move() + +def move_to_laser(): + robot.reset_motion() + tool = robot.tool + d = robot.get_distance_to_pnt("pLaser") + if d<0: + raise Exception ("Error calculating distance to laser: " + str(d)) + if d<POSITION_TOLERANCE: + print "FROM LASER" + robot.movel("pLaser", robot.tool, DESC_SCAN, sync = True) + return + d = robot.get_distance_to_pnt("pLaserHome") + if d<0: + raise Exception ("Error calculating distance to laser appro: " + str(d)) + if d<POSITION_TOLERANCE: + print "FROM APPRO" + robot.movel("pLaser", robot.tool, DESC_SCAN, sync = True) + return + d = robot.get_distance_to_pnt("pHome") + if d<0: + raise Exception ("Error calculating distance to home: " + str(d)) + if d<POSITION_TOLERANCE: + print "FROM HOME" + robot.movej("pLaserHome", robot.tool, DESC_DEFAULT) + robot.movel("pLaser", robot.tool, DESC_SCAN, sync = True) + return + raise Exception ("Must be in home position to start move to laser") + + +def update_tool(tool=None, x_offset=0.0, y_offset=0.0, z_offset=0.0): + #Updating tool: + t=robot.get_tool_trsf(tool) + t[0]=t[0] - x_offset + t[1]=t[1] - y_offset + t[2]=t[2] - z_offset + robot.set_tool_trsf(t, tool) + print "Updated " + (str(robot.tool) if (tool is None) else tool) + ": " + str(t) + robot.save_program() + + +def assert_valid_address(segment, puck, sample): + if (segment == AUX_SEGMENT) and (puck == 1): + return + if is_string(segment): + segment = ord(segment.upper()) - ord('A') +1 + if segment<=0 or segment >6: + raise Exception ("Invalid segment") + if puck<=0 or puck >5: + raise Exception ("Invalid puck") + if sample<=0 or sample >16: + raise Exception ("Invalid sample") + if get_puck_dev(segment, puck).isDisabled(): + raise Exception ("Puck is disabled") + +def assert_valid_sample(sample): + if sample<=0 or sample >16: + raise Exception ("Invalid sample") + +def get_puck_name(segment, puck): + try: + assert_valid_address(segment, puck, 1) + if type(segment) is int: + segment = chr( ord('A') + (segment-1)) + elif is_string(segment): + segment = segment.upper() + else: + return None + return segment + str(puck) + except: + return None + +def get_sample_name(segment, puck, sample): + puck_name = get_puck_name(segment, puck) + return None if (puck_name is None) else puck_name + str(sample) + + +def is_pin_detected_in_scanner(): + samples = [] + for i in range(10): + samples.append(laser_distance.read()) + time.sleep(0.05) + av = mean(samples) + for s in samples: + if s<=1: + return False + if abs(s-av) > 0.1: + return False + return True \ No newline at end of file diff --git a/script/motion/trash.py b/script/motion/trash.py new file mode 100644 index 0000000..8b37f2c --- /dev/null +++ b/script/motion/trash.py @@ -0,0 +1,36 @@ +def trash(): + """ + """ + print "trash" + + if robot.simulated: + time.sleep(3.0) + return + + #Initial checks + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + + #Enabling + enable_motion() + + robot.move_heater(to_bottom = False) + robot.move_heater(to_bottom = True) + + try: + for i in range(3): + robot.open_tool() + time.sleep(0.5) + robot.close_tool() + time.sleep(0.5) + finally: + robot.open_tool() + + + robot.move_heater(to_bottom = False) + robot.move_cold() + + \ No newline at end of file diff --git a/script/motion/unmount.py b/script/motion/unmount.py new file mode 100644 index 0000000..546a5fd --- /dev/null +++ b/script/motion/unmount.py @@ -0,0 +1,87 @@ +def unmount(segment = None, puck = None, sample = None, force=False, auto_unmount = False): + """ + """ + print "unmount: ", segment, puck, sample, force + + is_aux = (segment == AUX_SEGMENT) + needs_chilling = not is_aux and (not robot.is_cold()) + needs_drying = is_aux and robot.is_cold() + + if (segment is None) or (puck is None) or (sample is None): + pos = get_setting("mounted_sample_position") + if pos is None: + raise Exception("Mounted sample position is not defined") + segment, puck , sample = pos[0:1], int(pos[1]), int(pos[2:]) + print "Mounted sample position: ", segment, puck , sample + is_aux = (segment == AUX_SEGMENT) + + #Initial checks + assert_valid_address(segment, puck, sample) + assert_puck_detected(segment, puck) + + if robot.simulated: + time.sleep(3.0) + update_samples_info_sample_unmount(get_puck_name(segment, puck), sample) + set_setting("mounted_sample_position", None) + return + + robot.assert_no_task() + robot.reset_motion() + robot.wait_ready() + robot.assert_cleared() + #robot.assert_in_known_point() + hexiposi.assert_homed() + assert_mount_position() + + set_status("Umounting: " + str(segment) + str(puck) + str(sample)) + + try: + if smart_magnet.get_supress() == True: + smart_magnet.set_supress(False) + time.sleep(0.2) + + smart_magnet.apply_resting() + + if not force: + if smart_magnet.check_mounted(idle_time=0.5, timeout = 3.0) == False: + raise Exception("No pin detected on gonio") + + #Enabling + enable_motion() + + if not is_aux: + set_hexiposi(segment) + + if not force: + visual_check_hexiposi(segment) + if needs_chilling: + robot.move_cold() + time.sleep(30.) + else: + if needs_drying: + dry(wait_cold=-1) + #location = robot.get_current_point() + + if not robot.is_gonio(): + robot.move_gonio() + + #smart_magnet.set_unmount_current() + + robot.get_gonio() + + #smart_magnet.apply_reverse() + #smart_magnet.apply_resting() + + if is_aux: + robot.move_aux() + robot.put_aux( sample) + else: + #TODO: Shuld check if smart magnet detection is off? + update_samples_info_sample_unmount(get_puck_name(segment, puck), sample) + robot.move_dewar() + robot.put_dewar(segment, puck, sample) + set_setting("mounted_sample_position", None) + finally: + if not auto_unmount: + smart_magnet.set_default_current() + smart_magnet.set_supress(True) diff --git a/script/setup/ExposureScan.py b/script/setup/ExposureScan.py new file mode 100644 index 0000000..7a1d438 --- /dev/null +++ b/script/setup/ExposureScan.py @@ -0,0 +1,33 @@ +import java.awt.Rectangle as Rectangle + +import ch.psi.pshell.imaging.Data as Data +class Exposure(Writable): + def write(self,pos): + #cam.setExposure(pos) + img.camera.setExposure(pos) +exposure=Exposure() + + +class Contrast(Readable): + def read(self): + data = img.getData() + #roi = Data(data.getRectSelection(500,300,700,600), False) + #return data.getGradientVariance(False, Rectangle(480,0,600,670)) + return data.getGradientVariance(False, None) +contrast=Contrast() + + +#a= lscan(exposure,img.getContrast(), 0.5, 1.0, 0.01, 0.5) +#a= lscan(exposure,contrast, 0.2, 0.4, 0.01, 0.7) +ret= lscan(exposure,contrast, 10.0, 150.0, 5.0, 0.5) +y, x = ret.getReadable(0), ret.getPositions(0) + +#(n, m, s) = fit(a.getReadable(0), xdata=a.getPositions(0)) +#if m is None: +# m=max(a.getReadable(0)) +m=x[y.index(max(y))] +p=get_plots()[0] +p.addMarker(m, p.AxisId.X, str(m), Color.RED) + +print "Setting exposure = ", m +exposure.write(m) diff --git a/script/setup/Layout.py b/script/setup/Layout.py new file mode 100644 index 0000000..5c584f4 --- /dev/null +++ b/script/setup/Layout.py @@ -0,0 +1,292 @@ +################################################################################################### +#DEFINITIONS +################################################################################################### + +PLATE_SIZE = 480 +BLOCK_ROI_TOLERANCE = 12 #mm +LED_TOLERANCE = 8 #mm Distance between LEDs = 18mm +PUCK_SIZE = 65 + +DET_UNIPUCK = "unipuck" +DET_MINISPINE = "minispine" +DET_ERROR = "error" +DET_EMPTY = "empty" +DET_UNKNOWN = "unknown" + +BLOCKS = ('A', 'B', 'C', 'D', 'E', 'F') + +#Layout table +puck_layout = ( + #Num Elm A0 Index A1 Uni Mini Center Angle Xuni Yuni Xmini=Xc Ymini==Yc + (1 , 'A', 0 , 1, 0.00 , 57.00 , 75.00 , 66.00 , 0.00 , 0.00 , 57.00 , 0.00 , 75.00 ), + (2 , 'A', 0 , 2, 0.00 , 132.00, 150.00, 141.00, 0.00 , 0.00 , 132.00 , 0.00 , 150.00 ), + (3 , 'F', 0 , 5, 19.11, 180.40, 198.40, 189.40, 19.11 , 59.06 , 170.46 , 64.95 , 187.47 ), + (4 , 'F', 0 , 4, 40.89, 180.40, 198.40, 189.40, 40.89 , 118.09 , 136.38 , 129.87 , 149.98 ), + (5 , 'F', 0 , 3, 30.00, 111.90, 129.90, 120.90, 30.00 , 55.95 , 96.91 , 64.95 , 112.50 ), + (6 , 'F', 60 , 1, 0.00 , 57.00 , 75.00 , 66.00 , 60.00 , 49.36 , 28.50 , 64.95 , 37.50 ), + (7 , 'F', 60 , 2, 0.00 , 132.00, 150.00, 141.00, 60.00 , 114.32 , 66.00 , 129.90 , 75.00 ), + (8 , 'E', 60 , 5, 19.11, 180.40, 198.40, 189.40, 79.11 , 177.15 , 34.08 , 194.83 , 37.48 ), + (9 , 'E', 60 , 4, 40.89, 180.40, 198.40, 189.40, 100.89, 177.15 , -34.08 , 194.83 , -37.48 ), + (10, 'E', 60 , 3, 30.00, 111.90, 129.90, 120.90, 90.00 , 111.90 , 0.00 , 129.90 , 0.00 ), + (11, 'E', 120, 1, 0.00 , 57.00 , 75.00 , 66.00 , 120.00, 49.36 , -28.50 , 64.95 , -37.50 ), + (12, 'E', 120, 2, 0.00 , 132.00, 150.00, 141.00, 120.00, 114.32 , -66.00 , 129.90 , -75.00 ), + (13, 'D', 120, 5, 19.11, 180.40, 198.40, 189.40, 139.11, 118.09 , -136.38, 129.87 , -149.98), + (14, 'D', 120, 4, 40.89, 180.40, 198.40, 189.40, 160.89, 59.06 , -170.46, 64.95 , -187.47), + (15, 'D', 120, 3, 30.00, 111.90, 129.90, 120.90, 150.00, 55.95 , -96.91 , 64.95 , -112.50), + (16, 'D', 180, 1, 0.00 , 57.00 , 75.00 , 66.00 , 180.00, 0.00 , -57.00 , 0.00 , -75.00 ), + (17, 'D', 180, 2, 0.00 , 132.00, 150.00, 141.00, 180.00, 0.00 , -132.00, 0.00 , -150.00), + (18, 'C', 180, 5, 19.11, 180.40, 198.40, 189.40, 199.11, -59.06 , -170.46, -64.95 , -187.47), + (19, 'C', 180, 4, 40.89, 180.40, 198.40, 189.40, 220.89, -118.09, -136.38, -129.87, -149.98), + (20, 'C', 180, 3, 30.00, 111.90, 129.90, 120.90, 210.00, -55.95 , -96.91 , -64.95 , -112.50), + (21, 'C', 240, 1, 0.00 , 57.00 , 75.00 , 66.00 , 240.00, -49.36 , -28.50 , -64.95 , -37.50 ), + (22, 'C', 240, 2, 0.00 , 132.00, 150.00, 141.00, 240.00, -114.32, -66.00 , -129.90, -75.00 ), + (23, 'B', 240, 5, 19.11, 180.40, 198.40, 189.40, 259.11, -177.15, -34.08 , -194.83, -37.48 ), + (24, 'B', 240, 4, 40.89, 180.40, 198.40, 189.40, 280.89, -177.15, 34.08 , -194.83, 37.48 ), + (25, 'B', 240, 3, 30.00, 111.90, 129.90, 120.90, 270.00, -111.90, 0.00 , -129.90, 0.00 ), + (26, 'B', 300, 1, 0.00 , 57.00 , 75.00 , 66.00 , 300.00, -49.36 , 28.50 , -64.95 , 37.50 ), + (27, 'B', 300, 2, 0.00 , 132.00, 150.00, 141.00, 300.00, -114.32, 66.00 , -129.90, 75.00 ), + (28, 'A', 300, 5, 19.11, 180.40, 198.40, 189.40, 319.11, -118.09, 136.38 , -129.87, 149.98 ), + (29, 'A', 300, 4, 40.89, 180.40, 198.40, 189.40, 340.89, -59.06 , 170.46 , -64.95 , 187.47 ), + (30, 'A', 300, 3, 30.00, 111.90, 129.90, 120.90, 330.00, -55.95 , 96.91 , -64.95 , 112.5 ), + ) + +################################################################################################### +#Puck class +################################################################################################### +class Puck: + def __init__(self, id, block, index, angle, center, led_uni, led_mini): + self.id = id + self.block = block + self.index = index + self.angle = angle + self.center = center + self.led_uni = led_uni + self.led_mini = led_mini + self.detect = DET_UNKNOWN + + def __str__(self): + return "Number: " + str(self.id) + "\nBlock: " + str(self.block) + "\nIndex: " + str(self.index) + "\nAngle: " + str(self.angle) + \ + "\nCenter: " + str(self.center) + "\nLed Unipuck: " + str(self.led_uni) + "\nLed Minispine: " + str(self.led_mini) + + def get_name(self): + return str(self.block) + str(self.index) + + def match(self, x, y): + if math.hypot(x-self.led_uni[0], y-self.led_uni[1]) <= LED_TOLERANCE: + return DET_UNIPUCK + if math.hypot(x-self.led_mini[0], y-self.led_mini[1]) <= LED_TOLERANCE: + return DET_MINISPINE + return None + + + +_block_ids = [] +_puck_list = [] +_block_list = [] + +for p in(puck_layout): + puck = Puck(p[0], p[1], p[3], p[8], (p[11],p[12]), (p[9],p[10]), (p[11],p[12])) + _puck_list.append(puck) + if puck.block not in (_block_ids): + _block_ids.append(puck.block) + +def get_puck(id): + for p in _puck_list: + if id==p.id: + return p + return None + +def get_pucks(block = None): + ret = [] + for p in _puck_list: + if (block is None) or (block==p.block): + ret.append(p) + return ret + + +################################################################################################### +#Block class +################################################################################################### + +class Block: + def __init__(self, id, angle_range, x_range, y_range): + self.id = id + self.angle_range = angle_range + self.x_range = x_range + self.y_range = y_range + self.roi = (self.x_range[0] - BLOCK_ROI_TOLERANCE, self.y_range[0] - BLOCK_ROI_TOLERANCE, + self.x_range[1] + BLOCK_ROI_TOLERANCE, self.y_range[1] + BLOCK_ROI_TOLERANCE) + + def __str__(self): + return "Id: " + str(self.id) + "\nAngle: " + str(self.angle_range) + "\nX: " + str(self.x_range) + "\nY: " + str(self.y_range) + + +for id in _block_ids: + pucks = get_pucks(id) + angles, x, y = [], [], [] + for p in pucks: + angles.append(p.angle) + x.append(p.led_uni[0]) + x.append(p.led_mini[0]) + y.append(p.led_uni[1]) + y.append(p.led_mini[1]) + el = Block(id,(min(angles), max(angles)), (min(x), max(x)), (min(y), max(y))) + _block_list.append(el) + +def get_block(id): + for e in _block_list: + if id==e.id: + return e + return None + +def get_blocks(): + return _block_list + + + + +################################################################################################### +#Detection utilities +################################################################################################### + + +def _detect_puck(point_list, puck): + puck.detect = DET_ERROR + for point in point_list: + match = puck.match(point[0], point[1]) + if match is not None: + if match==DET_UNIPUCK: + puck.detect = DET_EMPTY if (puck.detect==DET_MINISPINE) else DET_UNIPUCK + elif match==DET_MINISPINE: + puck.detect = DET_EMPTY if (puck.detect==DET_UNIPUCK) else DET_MINISPINE + +def detect_pucks(point_list, id=None): + if (id is None) or (id in BLOCKS): + for puck in get_pucks(id): + _detect_puck(point_list, puck) + else: + puck = get_puck(int(id)) + print puck + _detect_puck(point_list, puck) + + +def clear_detection(block_id=None): + for puck in get_pucks(block_id): + puck.detect = DET_UNKNOWN + return get_puck_detection_dict(block_id) + + +def get_puck_detection(det_type, block_id=None): + ret = [] + for puck in get_pucks(block_id): + if puck.detect == det_type: + ret.append(puck) + return ret + +def get_unipucks(block_id=None): + return get_puck_detection(DET_UNIPUCK, block_id) + +def get_minispines(block_id=None): + return get_puck_detection(DET_MINISPINE, block_id) + +def get_empties(block_id=None): + return get_puck_detection(DET_EMPTY, block_id) + +def get_unknowns(block_id=None): + return get_puck_detection(DET_UNKNOWN, block_id) + +def get_det_errors(block_id=None): + return get_puck_detection(DET_ERROR, block_id) + +def get_puck_detection_dict(block_id): + ret = {} + pucks = [] + for puck in get_unipucks(block_id): + pucks.append(puck.get_name()) + pucks.sort() + ret["Unipuck"] = pucks + pucks = [] + for puck in get_minispines(block_id): + pucks.append(puck.get_name()) + pucks.sort() + ret["Minispine"] = pucks + pucks = [] + for puck in get_det_errors(block_id): + pucks.append(puck.get_name()) + pucks.sort() + ret["Error"] = pucks + pucks = [] + for puck in get_empties(block_id): + pucks.append(puck.get_name()) + pucks.sort() + ret["Empty"] = pucks + pucks = [] + for puck in get_unknowns(block_id): + pucks.append(puck.get_name()) + pucks.sort() + ret["Unknown"] = pucks + return ret + +################################################################################################### +#Plotting +################################################################################################### + +from plotutils import * + +def plot_base_plate(points = None, show_detect = True, title = None, p = None): + colors = (Color.RED, Color.BLUE, Color.MAGENTA, Color(128,0,128), Color(0,128,0), Color(255,128,0)) + if p is None: p = plot(None, title=title)[0] + p.getAxis(p.AxisId.Y).setInverted(True) + plot_circle(p, 0, 0, PLATE_SIZE/2, width = 0, color = Color.GRAY, name = "Plate") + plot_point(p, 0, 0, size = 10, color = Color.GRAY, name = "Center") + #p.setLegendVisible(True) + for block in get_blocks(): + (xmin, xmax) = block.x_range + (ymin, ymax) = block.y_range + (xmin, ymin, xmax, ymax ) = block.roi + index = get_blocks().index(block) + r = plot_rectangle(p, xmin, ymin, xmax, ymax, width =0, color=colors[index], name = block.id) + #In the first time the plot shows, it takes some time for the color to be assigned + #while r.color is None: + # time.sleep(0.001) + + if block.id in ('A', 'F'): + x, y = (xmin + xmax)/2, ymax + 5 + elif block.id in ('C', 'D'): + x, y = (xmin + xmax)/2, ymin - 5 + elif block.id == 'B': + x, y = xmax + 5, (ymin + ymax)/2 + elif block.id == 'E': + x, y = xmin - 5, (ymin + ymax)/2 + + p.addText(x,y, str(block.id), r.color) + + for puck in get_pucks(block.id): + (xu, yu) = puck.led_uni + (xm, ym) = puck.led_mini + plot_point(p, xu, yu, size = 3, color = r.color, name = str(puck.id)+"u") + plot_point(p, xm, ym, size = 7, color = r.color, name = str(puck.id)+"m") + plot_circle(p, xu, yu, LED_TOLERANCE, width = 0, color = r.color, name = str(puck.id)+"uc") + plot_circle(p, xm, ym, LED_TOLERANCE, width = 0, color = r.color, name = str(puck.id)+"mc") + p.addText((xu+xm)/2, (yu+ym)/2, str(puck.id), r.color) + c,w = Color.GRAY,0 + if show_detect: + if puck.detect == DET_UNIPUCK: + c,w = Color.BLACK,1 + elif puck.detect == DET_MINISPINE: + c,w = Color(150, 100, 50),1 + elif puck.detect == DET_ERROR: + c = Color(128,0,0) + plot_circle(p, xm, ym, PUCK_SIZE/2, width = w, color = c , name = str(puck.id)) + if points is not None: + for point in points: + c, w = Color.GRAY, 1 + for puck in get_pucks(): + match = puck.match(point[0], point[1]) + if match is not None: + w=2 + c = Color.DARK_GRAY if match == "minispine" else Color.BLACK + + + plot_cross(p,point[0], point[1], size = 12, width = w, color = c, name = "P"+ str(points.index(point))) + #plot_point(p,point[0], point[1], size = 5, color = Color.BLACK, name = "Pc"+ str(points.index(point))) diff --git a/script/tasks/LedMonitoring.py b/script/tasks/LedMonitoring.py new file mode 100644 index 0000000..5182a77 --- /dev/null +++ b/script/tasks/LedMonitoring.py @@ -0,0 +1,26 @@ +DEWAR_LEVEL_LED = 25.0 + +try: + _level = dewar_level.read() +except: + log("Cannot read Dewar level", False) + _level = 0.0 + +try: + _led_room_temp = is_led_room_temp() +except: + log("Cannot get LED configuration", False) + _led_room_temp = False + +if _level <= DEWAR_LEVEL_LED: + if not _led_room_temp: + log_str="LED Monitoring: Setting LEDs to room temperature range" + log(log_str, False) + print (log_str) + set_led_range(room_temp = True) +else: + if _led_room_temp: + log_str="LED Monitoring: Setting LEDs to LN2 range" + log(log_str, False) + print (log_str) + set_led_range(room_temp = False) diff --git a/script/test/CameraCalibration.py b/script/test/CameraCalibration.py new file mode 100644 index 0000000..02e7d9d --- /dev/null +++ b/script/test/CameraCalibration.py @@ -0,0 +1,71 @@ +import ch.psi.pshell.device.Camera as Camera +import ch.psi.pshell.imaging.RendererMode as RendererMode +from ch.psi.pshell.imaging.Overlays import * + +""" +img.camera.setColorMode(Camera.ColorMode.Mono) +img.camera.setDataType(Camera.DataType.UInt8) +img.camera.setGrabMode(Camera.GrabMode.Continuous) +img.camera.setTriggerMode(Camera.TriggerMode.Fixed_Rate) +img.camera.setExposure(50.00) +img.camera.setAcquirePeriod(200.00) +img.camera.setGain(0.0) +img.config.rotationCrop=True + + +""" +#img.camera.setROI(200, 0,1200,1200) + +img.camera.setROI(0, 0,1600,1200) +img.config.rotation=0 +img.config.roiX,img.config.roiY, img.config.roiWidth,img.config.roiHeight =0,0,-1,-1 +img.config.setCalibration(None) +img.camera.stop() +img.camera.start() + +#img.camera.setROI(300, 200,1000,1000) +#img.config.rotation=17 +#img.config.roiX,img.config.roiY, img.config.roiWidth,img.config.roiHeight = 50,50,900,900 + +p = show_panel(img) +p.setMode(RendererMode.Fit) +ov_text = Text(Pen(java.awt.Color.GREEN.darker()), "", java.awt.Font("Verdana", java.awt.Font.PLAIN, 24), java.awt.Point(20,20)) +ov_text.setFixed(True) + + + +p.addOverlay(ov_text) +try: + ov_text.update("Click on upper reference...") + p1 = p.waitClick(60000) + print p1 + ov_text.update("Click on left reference...") + p2 = p.waitClick(60000) + print p2 + ov_text.update("Click on right reference...") + p3 = p.waitClick(60000) + print p3 + + x, y, z = p1.x+p1.y*1j, p2.x+p2.y*1j, p3.x+p3.y*1j + w = z-x + w /= y-x + c = (x-y)*(w-abs(w)**2)/2j/w.imag-x + cx, cy, r = -c.real, -c.imag, abs(c+x) + a = math.degrees(math.atan((cx-p1.x)/(p1.y-cy))) + + print cx, cy, r, a + + #img.camera.setROI(int((1600-cx)/2),int((1200-cy)/2),1000,1000) + img.camera.setROI(int(cx-r),int(cy-r),int(2*r),int(2*r)) + img.config.rotation=-a + #remove rotation border + d=int(r/11) + img.config.roiX,img.config.roiY, img.config.roiWidth,img.config.roiHeight =d,d, int(2*r-2*d), int(2*r-2*d) + #img.config.setCalibration(None) + img.camera.stop() + img.camera.start() + +finally: + p.removeOverlay(ov_text) + + \ No newline at end of file diff --git a/script/test/CoverDetection.py b/script/test/CoverDetection.py new file mode 100644 index 0000000..24a228b --- /dev/null +++ b/script/test/CoverDetection.py @@ -0,0 +1,116 @@ +################################################################################################### +# Procedure to detect the cover orientation +################################################################################################### +import ch.psi.pshell.imaging.Utils.integrateVertically as integrateVertically +img.backgroundEnabled=False + +REF = (0,96,125) + +line = load_image("{images}/line.png", title="Line") +#line = load_image("{images}/line360.png", title="Line") + +line.getProcessor().setBackgroundValue(0.0) + + +#ip = get_image() +ip = integrate_frames(10) +ip = grayscale(ip, True) + + +smooth(ip) +#bandpass_filter(ip, 30, 1000) +edges(ip) + +#invert(ip) +#auto_threshold(ip, method = "Default") + + +#auto_threshold(ip, method = "Li") +auto_threshold(ip, method = "MaxEntropy") + +""" +for m in AutoThresholder.getMethods(): + print m + aux = ip.duplicate() + auto_threshold(aux, method = m) + binary_fill_holes(aux, dark_background=False) + renderer = show_panel(aux.bufferedImage) + time.sleep(1.0) +""" +#binary_dilate(ip, dark_background=False) +#binary_fill_holes(ip, dark_background=False) +#binary_open(ip, dark_background=Tr) + +renderer = show_panel(ip.bufferedImage) + + + + + + + + +#line = sub_image(line, 325, 325, 512, 512) +#ip = sub_image(ip, 325, 325, 512, 512) +line = sub_image(line, 453, 453, 256, 256) +ip = sub_image(ip, 453, 453, 256, 256) +#op = op_fft(ip, line, "correlate") + + +renderer = show_panel(ip.bufferedImage) + +#renderer = show_panel(op.bufferedImage) +#line.show() +ydata = [] +xdata = range (0,180,1) +for i in xdata: + l = line.duplicate() + l.getProcessor().setBackgroundValue(0.0) + l.getProcessor().rotate(float(i)) + op = op_fft(ip, l, "correlate") + bi = op.getBufferedImage() + p = integrateVertically(bi) + ydata.append(sum(p)) + + #renderer = show_panel(op.bufferedImage) + #time.sleep(0.001) + +def moving_average(arr, n) : + ret = [] + for i in range(len(arr)): + ret.append(mean(arr[max(i-n,0):min(i+n,len(arr)-1)])) + return ret +av = moving_average(ydata, 1) + +p = plot(ydata, xdata=xdata)[0] + +p.addSeries(LinePlotSeries("Moving Average")) +p.getSeries(1).setData(xdata, av) + +peaks = estimate_peak_indexes(ydata, xdata, (min(ydata) + max(ydata))/2, 25.0) +left, right = min(peaks), max(peaks) +if xdata[left]<5 and xdata[right]>(xdata[-1]-5): + #del peaks[0 if ydata[right] > ydata[left] else -1] + peaks.remove(right if ydata[right] > ydata[left] else left) + +peaks = sorted(peaks[:3]) +peaks_x = map(lambda x:xdata[x], peaks) +peaks_y = map(lambda x:ydata[x], peaks) + +print "Peaks", peaks +print "Peak indexes: " + str(peaks_x) +print "Peak values: " + str(peaks_y) + + +for i in range(len(peaks)): + peak = xdata[peaks[i]] + p.addMarker(peak, None, "N="+str(round(peak,2)), Color(80,0,80)) + if ((peaks[i]>160) and (REF[i]<20)): + peaks[i] = peaks[i] - 180.0 + +print "Peaks x: " + str(peaks_x) + + +d = mean(arrabs(arrsub(REF, peaks_x))) + +print "Angle = ", d \ No newline at end of file diff --git a/script/test/PuckDetection.py b/script/test/PuckDetection.py new file mode 100644 index 0000000..003ef68 --- /dev/null +++ b/script/test/PuckDetection.py @@ -0,0 +1,24 @@ +################################################################################################### +# Example of using ImageJ functionalities through ijutils. +################################################################################################### + +from ijutils import * +import java.awt.Color as Color + + +#Image Loading +ip = load_image("{images}/test2.png", title="Image") + + +#Puck Detection +aux = grayscale(ip, in_place=False) +aux.show() +plot(get_histogram(aux)) + +subtract_background(aux) +threshold(aux,0,50); aux.repaintWindow() +binary_fill_holes(aux); aux.repaintWindow() +(results,output_img)=analyse_particles(aux, 10000,50000, + fill_holes = False, exclude_edges = True,print_table=True, + output_image = "outlines", minCirc = 0.0, maxCirc = 1.0) +output_img.show() \ No newline at end of file diff --git a/script/test/PuckDetectionTest.py b/script/test/PuckDetectionTest.py new file mode 100644 index 0000000..2995f9a --- /dev/null +++ b/script/test/PuckDetectionTest.py @@ -0,0 +1,11 @@ +import datetime +index = 0 +prefix = str(datetime.datetime.now().strftime("%Y%m%d_%H%M%S")) + +while True: + suffix = "%04d - " % index + print (suffix), + run("imgproc/LedDetectionProc.py") + index=index+1 + save_image(image, "{images}/" +prefix + "_" + suffix +".png", "png") + \ No newline at end of file diff --git a/script/test/RobotCartesianScan.py b/script/test/RobotCartesianScan.py new file mode 100644 index 0000000..4a5225e --- /dev/null +++ b/script/test/RobotCartesianScan.py @@ -0,0 +1,28 @@ +import plotutils +from mathutils import fit_gaussian, Gaussian + +robot.enable() +move_to_laser() + +#robot.reset_motion("jLaser") + +#import ch.psi.pshell.device.Timestamp as Timestamp +#sensor = Timestamp() + +#ret = lscan(robot_z, sensor, -50.0, 0.0, 0.5, latency = 0, relative = True) +#ret = lscan(robot_x, sensor, -50.0, 0.0, 0.5, latency = 0, relative = True) + +robot.set_motors_enabled(True) +ret = lscan(robot_x, ue.readable, -1.5, 1.5, 0.1, latency = 0.01, relative = True) + +x,y = ret.getPositions(0), ret.getReadable(0) +y = [100.0-v for v in y] +(norm, mea, sigma) = fit(y, xdata=x) +print "Maximum at " + str(mea) + + + +robot.set_motors_enabled(True) +ret = lscan(robot_rz, ue.readable, 0.0, 40.0, 1.0, latency = 0.01, relative = True, range = "auto") + + diff --git a/script/test/SampleDataInput.py b/script/test/SampleDataInput.py new file mode 100644 index 0000000..1f00cd6 --- /dev/null +++ b/script/test/SampleDataInput.py @@ -0,0 +1,1861 @@ +USER_NAME = "My User" +DEWAR_NAME = "My Dewar" + +test_sample_data = [ \ + +#Puck A1 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Isabelle Chip", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "flat_Base_Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Isabelle Chip", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "flat_Base_Pin_2", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Isabelle Chip", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "regular_Base_Pin_1", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Isabelle Chip", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "A1",\ + "sampleName": "regular_Base_Pin_2", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + +# Puck B1 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + \"sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + +# Puck B2 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + +# Puck B3 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + +# Puck B4 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "u"dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + +# Puck C1 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + +# Puck C2 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + +# Puck D1 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + +# Puck D2 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus""sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "u"dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ +# Puck D3 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ +# Puck D4 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "XXX", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + ] + + +set_samples_info(test_sample_data) \ No newline at end of file diff --git a/script/test/SampleDataInput_Dominik.py b/script/test/SampleDataInput_Dominik.py new file mode 100644 index 0000000..8ff4ae7 --- /dev/null +++ b/script/test/SampleDataInput_Dominik.py @@ -0,0 +1,1862 @@ +USER_NAME = "My User" +DEWAR_NAME = "My Dewar" + +test_sample_data = [ \ + #Puck A1 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Isabelle Chip", \ + "puckBarcode": "CA00CF1471", \ + "puckType": "unipuck", \ + "puckAddress": "",\ + "sampleName": "flat_Base_Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Isabelle Chip", \ + "puckBarcode": "CA00CF1471", \ + "puckType": "unipuck", \ + "puckAddress": "",\ + "sampleName": "flat_Base_Pin_2", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Isabelle Chip", \ + "puckBarcode": "CA00CF1471", \ + "puckType": "unipuck", \ + "puckAddress": "",\ + "sampleName": "regular_Base_Pin_1", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Isabelle Chip", \ + "puckBarcode": "CA00CF1471", \ + "puckType": "unipuck", \ + "puckAddress": "",\ + "sampleName": "regular_Base_Pin_2", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + # Puck B1 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "IDatamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_1", \ + "puckBarcode": "DMBW1", \ + "puckType": "unipuck", \ + "puckAddress": "B1",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck B2 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW2", \ + "puckType": "unipuck", \ + "puckAddress": "B2",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck B3 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_2", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_3", \ + "puckBarcode": "DMBW3", \ + "puckType": "unipuck", \ + "puckAddress": "B3",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck B4 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Black_White_4", \ + "puckBarcode": "DMBW4", \ + "puckType": "unipuck", \ + "puckAddress": "B4",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck C1 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_1", \ + "puckBarcode": "DMGA1", \ + "puckType": "unipuck", \ + "puckAddress": "C1",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck C2 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "Datamatrix_Grey_Alu_2", \ + "puckBarcode": "DMGA2", \ + "puckType": "unipuck", \ + "puckAddress": "C2",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck D1 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_1", \ + "puckBarcode": "NODM1", \ + "puckType": "unipuck", \ + "puckAddress": "D1",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck D2 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_2", \ + "puckBarcode": "NODM2", \ + "puckType": "unipuck", \ + "puckAddress": "D2",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck D3 \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_3", \ + "puckBarcode": "NODM3", \ + "puckType": "unipuck", \ + "puckAddress": "D3",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + \ + # Puck D4 + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_1", \ + "samplePosition": 1,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_2", \ + "samplePosition": 2,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_3", \ + "samplePosition": 3,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_4", \ + "samplePosition": 4,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_5", \ + "samplePosition": 5,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_6", \ + "samplePosition": 6,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_7", \ + "samplePosition": 7,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_8", \ + "samplePosition": 8,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_9", \ + "samplePosition": 9,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_10", \ + "samplePosition": 10,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_11", \ + "samplePosition": 11,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_12", \ + "samplePosition": 12,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_13", \ + "samplePosition": 13,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_14", \ + "samplePosition": 14,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_15", \ + "samplePosition": 15,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + { "userName": USER_NAME, \ + "dewarName": DEWAR_NAME, \ + "puckName": "No_Datamatrix_4", \ + "puckBarcode": "NODM4", \ + "puckType": "unipuck", \ + "puckAddress": "D4",\ + "sampleName": "Pin_16", \ + "samplePosition": 16,\ + "sampleBarcode": "", \ + "sampleStatus": "Present", \ + "sampleMountCount": 0, + } , \ + ] +set_samples_info(test_sample_data) \ No newline at end of file diff --git a/script/test/SampleDetection.py b/script/test/SampleDetection.py new file mode 100644 index 0000000..4638b7a --- /dev/null +++ b/script/test/SampleDetection.py @@ -0,0 +1,23 @@ +################################################################################################### +# Example of using ImageJ functionalities through ijutils. +################################################################################################### + +from ijutils import * +import java.awt.Color as Color + +#Image Loading +ip = load_image("{images}/test2.png", title="Image") + +aux = grayscale(ip, in_place=False) +aux.show() + +invert(aux); aux.repaintWindow() +#gaussian_blur(aux); aux.repaintWindow() +subtract_background(aux); aux.repaintWindow() +auto_threshold(aux); aux.repaintWindow() +binary_open(aux); aux.repaintWindow() +#binary_fill_holes(aux); aux.repaintWindow() +(results,output_img)=analyse_particles(aux, 250,1000, + fill_holes = False, exclude_edges = True,print_table=True, + output_image = "outlines", minCirc = 0.7, maxCirc = 1.0) +output_img.show() diff --git a/script/test/TestAlign.py b/script/test/TestAlign.py new file mode 100644 index 0000000..0cbe1a7 --- /dev/null +++ b/script/test/TestAlign.py @@ -0,0 +1,9 @@ + +v = 2.0 +#while(true): +for i in range(100): + v = v * (-1.0) + robot_j4.initialize() + robot_j4.moveRel(v) + robot.align() + \ No newline at end of file diff --git a/script/test/TestBugPcAPI b/script/test/TestBugPcAPI new file mode 100644 index 0000000..5be0f3e --- /dev/null +++ b/script/test/TestBugPcAPI @@ -0,0 +1,4 @@ +while True: + img.initialize() + img.waitNext(10000) + time.sleep(2.0) \ No newline at end of file diff --git a/script/test/TestBugPcAPI.py b/script/test/TestBugPcAPI.py new file mode 100644 index 0000000..7a3d186 --- /dev/null +++ b/script/test/TestBugPcAPI.py @@ -0,0 +1,30 @@ +import ch.psi.pshell.prosilica.Prosilica as Prosilica +import ch.psi.pshell.device.Camera as Camera + + +add_device(Prosilica("img", 25001, "PacketSize=1522;PixelFormat=Mono8;BinningX=1;BinningY=1;RegionX=300;RegionY=200;Width=1000;Height=1000;MulticastEnable=Off"), True) + +img.camera.setGrabMode(Camera.GrabMode.Continuous) +img.camera.setTriggerMode(Camera.TriggerMode.Fixed_Rate) +img.camera.setExposure(50.00) +img.camera.setAcquirePeriod(200.00) +img.camera.setGain(0.0) +#img.camera.setROI(200, 0,1200,1200) +""" +img.camera.setROI(300, 200,1000,1000) +img.config.rotation=17 +img.config.rotationCrop=True +img.config.roiX,img.config.roiY, img.config.roiWidth,img.config.roiHeight = 50,50,900,900 +""" +img.camera.setROI(int(get_setting("roi_x")), int(get_setting("roi_y")), int(get_setting("roi_w")), int(get_setting("roi_h"))) + +img.camera.stop() +img.camera.start() + + +show_panel(img) +#while True: +# img.initialize() +# img.waitNext(1000) +# time.sleep(0.1) + diff --git a/script/test/TestBugPcAPI2.py b/script/test/TestBugPcAPI2.py new file mode 100644 index 0000000..5e92b37 --- /dev/null +++ b/script/test/TestBugPcAPI2.py @@ -0,0 +1,6 @@ +import ch.psi.pshell.imaging.MjpegSource as MjpegSource +MjpegSource2 = get_context().pluginManager.getDynamicClass("MjpegSource2") +add_device(MjpegSource("gripper_cam", "http://axis-accc8e9cc87b.psi.ch/axis-cgi/mjpg/video.cgi"), True) +#gripper_cam.polling=1000 +gripper_cam.monitored = True +show_panel(gripper_cam) \ No newline at end of file diff --git a/script/test/TestBugPcAPI3.py b/script/test/TestBugPcAPI3.py new file mode 100644 index 0000000..6acb775 --- /dev/null +++ b/script/test/TestBugPcAPI3.py @@ -0,0 +1,4 @@ +while True: + img.initialize() + img.waitNext(1000) + time.sleep(0.1) \ No newline at end of file diff --git a/script/test/TestCalib.py b/script/test/TestCalib.py new file mode 100644 index 0000000..2cc311b --- /dev/null +++ b/script/test/TestCalib.py @@ -0,0 +1,30 @@ + +print "calibrate_tool" + +#Initial checks +robot.assert_no_task() +robot.reset_motion() +robot.wait_ready() +robot.assert_cleared() +#robot.assert_in_known_point() + +#Enabling +enable_motion() + +(detected, dm) = move_scanner() + +if detected: + print "Pin detected, trashing..." + trash() + (detected, dm) = move_scanner() + if detected: + raise Exception("Cannot trash pin") + +robot.open_tool() +robot.get_calibration_tool() + +run("calibration/ToolCalibration3") + +robot.put_calibration_tool() + +robot.save_program() diff --git a/script/test/TestCameraStability1.py b/script/test/TestCameraStability1.py new file mode 100644 index 0000000..e4660e9 --- /dev/null +++ b/script/test/TestCameraStability1.py @@ -0,0 +1,11 @@ +for i in range(10): + time.sleep(2) + move_home() + time.sleep(1) + move_park() + start = time.time() + while get_img_cover_pos() != 'A': + print ".", + time.sleep(0.001) + print "Time = " , ( time.time() - start) + \ No newline at end of file diff --git a/script/test/TestCameraStability2.py b/script/test/TestCameraStability2.py new file mode 100644 index 0000000..c6ef878 --- /dev/null +++ b/script/test/TestCameraStability2.py @@ -0,0 +1,14 @@ +cover_detection_debug=True +while True: + for pos in ['A', 'B', 'C', 'D', 'E', 'F']: + print "Moving to ", pos + hexiposi.move(pos) + move_home() + move_park() + time.sleep(2.0) + ret = run("imgproc/CoverDetection") + det = ret[0] + print "Detected: ", det + if det != pos: + raise Exception("Position error") + diff --git a/script/test/TestCameraStability3.py b/script/test/TestCameraStability3.py new file mode 100644 index 0000000..bcf1327 --- /dev/null +++ b/script/test/TestCameraStability3.py @@ -0,0 +1,9 @@ +for i in range(10): + time.sleep(1) + move_home() + time.sleep(1) + move_park() + start = time.time() + time.sleep(1.0) + print run("imgproc/LedDetectionProc.py") + \ No newline at end of file diff --git a/script/test/TestCmdSynchronization.py b/script/test/TestCmdSynchronization.py new file mode 100644 index 0000000..098998d --- /dev/null +++ b/script/test/TestCmdSynchronization.py @@ -0,0 +1,32 @@ +import java.util.logging.Level + +def get_pos_str(): + return "point: " + str(robot.get_current_point()) + " - here: " + str(robot.here()) + " - herej: " + str(robot.herej()) + +enable_motion() + +get_context().setLogLevel(java.util.logging.Level.FINER) +try: + while True: + #robot.move_dewar() + #robot.move_park() + + log("Moving dewar", False) + flag = robot.start_task('moveDewar') + print "moveDewar: ", flag + log("Waiting", False) + ret = robot.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + log("Moving dewar finished (" + str(ret) + ") - pos: " + get_pos_str(), False) + robot.assert_dewar() + + + log("Moving park", False) + flag = robot.start_task('movePark') + print "movePark: ", flag + log("Waiting", False) + ret = robot.wait_task_finished(TASK_WAIT_ROBOT_POLLING) + log("Moving park finished (" + str(ret) + ") - pos: " + get_pos_str(), False) + robot.assert_park() + +finally: + get_context().setLogLevel(java.util.logging.Level.INFO) \ No newline at end of file diff --git a/script/test/TestCoverDetection.py b/script/test/TestCoverDetection.py new file mode 100644 index 0000000..e21e2c0 --- /dev/null +++ b/script/test/TestCoverDetection.py @@ -0,0 +1,19 @@ + +ca = [] +aa = [] +pa = [] + +#for i in range(6): + #index = i+1 +for i in ['A', 'B', 'C', 'D', 'E', 'F']: + hexiposi.move(i) + [position, angle, confidence] = run("imgproc/CoverDetection") + print [position, angle, confidence] + pa.append(position) + aa.append(angle) + ca.append(confidence) + +print "---" +print "Position: " ,pa +print "Angle: " ,aa +print "Confidence: " ,ca, " mean: ", mean(ca) \ No newline at end of file diff --git a/script/test/TestEuclidean.py b/script/test/TestEuclidean.py new file mode 100644 index 0000000..4376dc7 --- /dev/null +++ b/script/test/TestEuclidean.py @@ -0,0 +1,23 @@ +import org.apache.commons.math3.geometry.euclidean.threed.Segment as Segment +import org.apache.commons.math3.geometry.euclidean.threed.Vector3D as Vector3D +import org.apache.commons.math3.geometry.euclidean.threed.Line as Line + + +p = Vector3D(0, 0, 3) + +p1 = Vector3D(0,0,0) +p2 = Vector3D(0,1,1 ) +tolerance = 0.001 + +l = Line(p1, p2, tolerance) + + +print l.distance(p) +print p1.distance(p) +print p2.distance(p) +print "---" + +print l.getAbscissa(p) +print l.pointAt(l.getAbscissa(p)) + +#print l.closestPoint(Line(p, p, 0.01)) \ No newline at end of file diff --git a/script/test/TestLaserScan.py b/script/test/TestLaserScan.py new file mode 100644 index 0000000..a977ba0 --- /dev/null +++ b/script/test/TestLaserScan.py @@ -0,0 +1,12 @@ +robot.set_motors_enabled(True) +steps_x = 10 +steps_y = 8 +#ret = ascan([robot_x, robot_z], ue.readable, [-10.0, -10.0], [10.0, 10.0], [10,10], latency = 0.01, relative = True , zigzag=True) +ret = ascan([robot_x, robot_z], ue.readable, [-10.0, -10.0], [10.0, 10.0], [steps_y,steps_x], latency = 0.01, relative = True , zigzag=False) +data = Convert.transpose(Convert.toBidimensional(to_array(ret.getReadable(0),'d'),steps_x+1,steps_y+1)) +plot(data, title="data") + +data = ret.getData(0) +plot(data, title="data2") + + diff --git a/script/test/TestLayout.py b/script/test/TestLayout.py new file mode 100644 index 0000000..7404a8e --- /dev/null +++ b/script/test/TestLayout.py @@ -0,0 +1,21 @@ + + + +points = [(100, 140), (130, 77), (120, 130), (110, 100)] +clear_detection() +detect_pucks(points) +#detect_pucks(points, 'A') +#detect_pucks(points, '4') +plot_base_plate(points) + + + +#plot_detected_leds(points) + + + +block_id = None +print get_unipucks(block_id) +print get_minispines(block_id) +print get_empties(block_id) +print get_det_errors(block_id) \ No newline at end of file diff --git a/script/test/TestMicrohawk.py b/script/test/TestMicrohawk.py new file mode 100644 index 0000000..0ea517e --- /dev/null +++ b/script/test/TestMicrohawk.py @@ -0,0 +1,10 @@ +import ch.psi.pshell.serial.TcpDevice as TcpDevice +import ch.psi.pshell.serial.UdpDevice as UdpDevice + + +microscan = TcpDevice("microscan", "MicroHAWK38C528:2001") +#microscan = UdpDevice("microscan", "MicroHAWK38C528:2001") +microscan.initialize() + + + diff --git a/script/test/TestRecover.py b/script/test/TestRecover.py new file mode 100644 index 0000000..340853f --- /dev/null +++ b/script/test/TestRecover.py @@ -0,0 +1,15 @@ +print "Pos=" + str(robot.get_cartesian_pos()) +for p in robot.get_known_points(): + print p + " = " + str(get_pnt(p)) + +print "-------------" + +for segment in known_segments: + is_on_segment(segment) + +print "-------------" +for segment in known_segments: + try: + move_to_segment(segment) + except: + print sys.exc_info()[1] \ No newline at end of file diff --git a/script/test/TestRelays.py b/script/test/TestRelays.py new file mode 100644 index 0000000..adcd828 --- /dev/null +++ b/script/test/TestRelays.py @@ -0,0 +1,12 @@ +for i in range(500): + relay1.write(True) + time.sleep(1.2) + relay1.write(False) + time.sleep(1.2) +""" +for i in range(5): + relays.write(to_array([True,]*16, 'z')) + time.sleep(0.2) + relays.write(to_array([False,]*16, 'z')) + time.sleep(0.2) +""" \ No newline at end of file diff --git a/script/test/TestRemoveBackground.py b/script/test/TestRemoveBackground.py new file mode 100644 index 0000000..7376f07 --- /dev/null +++ b/script/test/TestRemoveBackground.py @@ -0,0 +1,31 @@ +number_frames = 5 +number_backgrounds = 5 +minimum_size = 78 # r = 5 # 150 +maximum_size = 750 # r = 15 #1500 +min_circ = 0.2 + +threshold_method = "MaxEntropy" +threshold_method,threshold_range = "Manual", (0, 215) + +exclude_edges = True +led_latency = 0.5 #0.1 + +set_led_state(False) +time.sleep(led_latency) +img.waitNext(2000) + +background = average_frames(number_backgrounds) +#background = integrate_frames(number_backgrounds) + +set_led_state(True) +time.sleep(led_latency) +img.waitNext(2000) +image = average_frames(number_frames) +#image = integrate_frames(number_frames) + +set_led_state(False) + +op_image(image, background, "subtract", float_result=True, in_place=True) +image=grayscale(image) + +show_panel(image.getBufferedImage()) \ No newline at end of file diff --git a/script/test/TestRobot.py b/script/test/TestRobot.py new file mode 100644 index 0000000..d64599f --- /dev/null +++ b/script/test/TestRobot.py @@ -0,0 +1,41 @@ +robot.task_create("simulateEvents",3, name = "test", priority = 20) +print robot.get_task_status("test") +print robot.get_task_status("tests") + +robot.task_suspend("test") +print robot.get_task_status("test") +robot.task_resume("test") +print robot.get_task_status("test") + +robot.task_kill("test") +print robot.get_task_status("test") + + +print robot.is_powered() +print robot.get_monitor_speed() +#print robot.set_monitor_speed(20) +#print robot.enable() +print robot.disable() +print robot.is_calibrated() +print robot.read_working_mode() +print robot.get_emergency_stop_sts() +print robot.get_safety_fault_signal() +print robot.stop() +print robot.resume() +print robot.reset_motion() +print robot.is_empty() +print robot.is_settled() +print robot.get_move_id() +print robot.set_move_id(10) +print robot.get_joint_forces() +#print robot.open("gripper") +#print robot.close("gripper") +print robot.herej() +print robot.distance_t("t", "t") +print robot.distance_p("p", "p") +print robot.compose( "p", "world", "t") +print robot.here("gripper", "world") +print robot.joint_to_point("gripper", "world", "j") +print robot.point_to_joint("gripper", "j", "p") +print robot.position("p", "world") +print robot.mount(1, 2) diff --git a/script/test/TestRobot2.py b/script/test/TestRobot2.py new file mode 100644 index 0000000..68398b8 --- /dev/null +++ b/script/test/TestRobot2.py @@ -0,0 +1,72 @@ +import traceback + +robot.task_create("simulateEvents",3, name = "test", priority = 20) + +step = 0 +try: + while(True): + start = time.time() + step = 1 + robot.is_powered() + step = 2 + robot.get_task_status("test") + step = 3 + robot.get_monitor_speed() + step = 4 + #robot.set_monitor_speed(20) + #robot.enable() + step = 5 + #robot.disable() + step = 6 + robot.is_calibrated() + step = 7 + robot.read_working_mode() + step = 8 + robot.get_emergency_stop_sts() + step = 9 + robot.get_safety_fault_signal() + step = 10 + robot.stop() + step = 11 + robot.resume() + step = 12 + robot.reset_motion() + step = 13 + robot.is_empty() + step = 14 + robot.is_settled() + step = 15 + robot.get_move_id() + step = 16 + robot.set_move_id(10) + step = 17 + robot.get_joint_forces() + step = 18 + #robot.open_tool("gripper") + #robot.close_tool("gripper") + robot.herej() + step = 19 + robot.distance_t("t", "t") + step = 20 + robot.distance_p("p", "p") + step = 21 + robot.compose( "p", "world", "t") + step = 22 + robot.here("gripper", "world") + step = 23 + robot.joint_to_point("gripper", "world", "j") + step = 24 + robot.point_to_joint("gripper", "j", "p") + step = 25 + robot.position("p", "world") + step = 26 + robot.mount(1, 2) + #print time.time()-start +except: + print >> sys.stderr, traceback.format_exc() +finally: + print "Step: " + str(step) + try: + robot.task_kill("test") + except: + pass \ No newline at end of file diff --git a/script/test/TestRobotCmds.py b/script/test/TestRobotCmds.py new file mode 100644 index 0000000..4225281 --- /dev/null +++ b/script/test/TestRobotCmds.py @@ -0,0 +1,32 @@ + +import java.lang.System as System + +index = 0 +max_time = 0 +while True: + start = System.currentTimeMillis() + robot.execute(1,1,1) + time.sleep(0.01) + robot.execute(2,1,1) + time.sleep(0.01) + robot.execute(1,1,1) + time.sleep(0.01) + robot.execute(2,1,1) + time.sleep(0.01) + robot.execute(1,1,1) + time.sleep(0.01) + robot.execute(2,1,1) + time.sleep(0.01) + robot.execute(1,1,1) + time.sleep(0.01) + robot.execute(2,1,1) + time.sleep(0.01) + robot.execute(1,1,1) + time.sleep(0.01) + robot.execute(2,1,1) + time.sleep(0.01) + cur_time = System.currentTimeMillis() - start + max_time = max(cur_time, max_time) + print index, cur_time, max_time + index = index + 1 + \ No newline at end of file diff --git a/script/test/TestRobotCmds2.py b/script/test/TestRobotCmds2.py new file mode 100644 index 0000000..048e20e --- /dev/null +++ b/script/test/TestRobotCmds2.py @@ -0,0 +1,25 @@ +if robot_req.read() != 0: + raise Exception("Ongoing command") +if robot_ack.read() != 0: + raise Exception("Robot is not ready") +robot_cmd.write(1) +args = [0,0,0,0,0,0] + +robot_args.write(to_array(args, 'i')) + + +robot_req.write(1) +while robot_ack.read() == 0: + time.sleep(0.001) + +err = robot_ack.take() +if err == 1: + ret = robot_ret.read() + print ret +if err == 2: + print ("Invalid command: " + str(command)) +print ("Unknown error: " + str(err)) +robot_req.write(0) +while robot_ack.read() != 0: + time.sleep(0.001) + diff --git a/script/test/cycle_time b/script/test/cycle_time new file mode 100644 index 0000000..79c790e --- /dev/null +++ b/script/test/cycle_time @@ -0,0 +1,4 @@ +start =time.time() +unmount('A',2,5, force=True) +mount('A',2,5, force=True, read_dm=False) +print time.time()-start \ No newline at end of file diff --git a/script/test/imgtest.py b/script/test/imgtest.py new file mode 100644 index 0000000..de442c2 --- /dev/null +++ b/script/test/imgtest.py @@ -0,0 +1,47 @@ +################################################################################################### +# Example of using ImageJ functionalities through ijutils. +################################################################################################### + +from ijutils import * +import java.awt.Color as Color + +import ch.psi.pshell.imaging.Filter as Filter +from ch.psi.pshell.imaging.Overlays import * +import ch.psi.pshell.imaging.Pen as Pen + + + +def detect_pucks(ip): + aux = grayscale(ip, in_place=False) + threshold(aux,0,50) + binary_fill_holes(aux) + return analyse_particles(aux, 10000,50000, + fill_holes = False, exclude_edges = True,print_table=True, + output_image = "outlines", minCirc = 0.4, maxCirc = 1.0) + +def detect_samples(ip): + aux = grayscale(ip, in_place=False) + invert(aux) + subtract_background(aux) + auto_threshold(aux) + binary_open(aux) + return analyse_particles(aux, 300,800, + fill_holes = False, exclude_edges = True,print_table=True, + output_image = "outlines", minCirc = 0.4 + , maxCirc = 1.0) + + +class MyFilter(Filter): + def process(self, image, data): + ip = load_image(image) + (results_puck,output_puck) = detect_pucks(ip) + (results_samples,output_samples) = detect_samples(ip) + set_lut(output_puck, outline_lut1[0], outline_lut1[1], outline_lut1[2]) + set_lut(output_samples, outline_lut2[0], outline_lut2[1], outline_lut2[2]) + op_image(ip, output_samples, "xor") + op_image(ip, output_puck, "xor") + return ip.getBufferedImage() + +#Setting the filter to a source +img.setFilter(MyFilter()) + diff --git a/script/test/ip b/script/test/ip new file mode 100644 index 0000000..e79bb62 --- /dev/null +++ b/script/test/ip @@ -0,0 +1,15 @@ +from ijutils import * +import java.awt.Color as Color + +ip = load_image(img.getImage()) +grayscale(ip) +#ip=binning(ip,2) +gaussian_blur(ip) +#bandpass_filter(ip,20, 100) +auto_threshold(ip) + +#Particle Analysis +(results,output_img)=analyse_particles(ip, 500,2000, print_table=True) +output_img.show() + +ip.show() \ No newline at end of file diff --git a/script/test/onewire.py b/script/test/onewire.py new file mode 100644 index 0000000..5141067 --- /dev/null +++ b/script/test/onewire.py @@ -0,0 +1,122 @@ +import traceback + +class Detector(ReadonlyRegisterBase): + def __init__(self, name): + ReadonlyRegisterBase.__init__(self, name) + self.id = None + self.sn = None + self.status = None + self.type = None + self.set_inputs({}) + + def set_inputs(self, inputs): + self.inputs = inputs + self.setCache(inputs.values(), None) + if (len(self.take()) == 0): + self.setState(State.Offline) + else: + self.setState(State.Ready) + + def set_input(self, index, val): + self.inputs[index] = val + self.set_inputs(self.inputs) + +class Esera(TcpDevice): + def __init__(self, name, server, timeout = 1000, retries = 1): + TcpDevice.__init__(self, name, server) + self.setMode(self.Mode.FullDuplex) + self.detectors = [] + self.complete = False + + def start(self): + self.write("set,sys,run,1\n") + + def stop(self): + self.write("set,sys,run,0\n") + + def list(self): + self.write("get,owb,listall1\n") + + def req_data(self): + self.write("get,sys,data\n") + + def doInitialize(self): + super(Esera, self).doInitialize() + try: + self.setState(State.Ready) #So can communicate + #self.stop() + #time.sleep(0.1) + #self.flush() + self.detectors = [] + for i in range(30): + self.detectors.append(Detector("Detector " + str(i+1))) + self.list() + time.sleep(0.5) + self.start() + self.req_data() + except: + print >> sys.stderr, traceback.format_exc() + getLogger().log(traceback.format_exc()) + raise + + def doUpdate(self): + if not self.complete: + init = True + for det in self.detectors: + if det.id == None: + init = False + break + if init: + self.complete = True + self.start() + + self.req_data() + #def onByte(self, rx): + # print rx + + def onString(self, msg): + print msg + tokens = msg.split("|") + if len(tokens)>1: + try: + if msg[:3] == "LST": + #LST|1_OWD1|3AF361270000009E|S_0|DS2413| + if tokens[1] > 1: + index = int(tokens[1].split("_")[1][3:]) - 1 + if index < len(self.detectors): + det = self.detectors[index] + det.id = tokens[1] + det.sn= tokens[2] if len(tokens)>2 else None + det.status = int(tokens[3][2:]) if len(tokens)>3 else None + det.type = tokens[4] if len(tokens)>4 else None + if det.status!= 0: + det.set_inputs({}) + else: + for det in self.detectors: + if det.id is not None and msg.startswith(det.id): + det_id = int(tokens[0][len(det.id)+1:]) + det.set_input(det_id, int(tokens[1])) + except: + print >> sys.stderr, traceback.format_exc() + getLogger().log(traceback.format_exc()) + + + + +#count = 1 +#while (True): +# print onewire.waitString("\n", 1000)# +# +# print count +# count = count + 1 + + + + + + +add_device(Esera("onewire", "129.129.126.83:5000"), force = True) +onewire.setPolling(1000) +add_device(onewire.detectors[0], force = True) +add_device(onewire.detectors[1], force = True) +add_device(onewire.detectors[2], force = True) diff --git a/script/test/test.py b/script/test/test.py new file mode 100644 index 0000000..92fcaca --- /dev/null +++ b/script/test/test.py @@ -0,0 +1,24 @@ +from ijutils import * +import java.awt.Color as Color + + +#ip = load_array(img.getData().getMatrix()) +ip = load_image(img.getOutput()) +#ip = load_image("{images}/test3.png", title="Image") + + +aux = grayscale(ip, in_place=False) +aux.show() + +#convolve(aux, KERNEL_SOBEL); aux.repaintWindow() + +invert(aux); aux.repaintWindow() +subtract_background(aux); aux.repaintWindow() +auto_threshold(aux); aux.repaintWindow() +binary_open(aux); aux.repaintWindow() + +(table, image) = analyse_particles(aux, 250,1000, + fill_holes = False, exclude_edges = True,print_table=True, + output_image = "outlines", minCirc = 0.82, maxCirc = 1.0) + +image.show() \ No newline at end of file diff --git a/script/test/test_hexiposi.py b/script/test/test_hexiposi.py new file mode 100644 index 0000000..324a480 --- /dev/null +++ b/script/test/test_hexiposi.py @@ -0,0 +1,8 @@ +index = 1 +while(True): + for pos in ['A', 'B', 'C', 'D', 'E', 'F']: + hexiposi.move(pos) + visual_check_hexiposi(pos) + print "Ok: " + pos + print index + index = index + 1 \ No newline at end of file diff --git a/script/test/test_swingutils.py b/script/test/test_swingutils.py new file mode 100644 index 0000000..65b354b --- /dev/null +++ b/script/test/test_swingutils.py @@ -0,0 +1,24 @@ +import ch.psi.pshell.imaging.RendererMode as RendererMode +import ch.psi.pshell.imaging.Calibration as Calibration +from ch.psi.pshell.imaging.Overlays import * +import ch.psi.utils.swing.SwingUtils as SwingUtils +import javax.swing.SwingUtilities as SwingUtilities +from swingutils.threads.swing import callSwing + + +p = show_panel(img) +dlg = SwingUtilities.getWindowAncestor(p) +dlg.setSize(800,800) +frm=SwingUtils.getFrame(p) +dlg.setLocationRelativeTo(frm) + +def update_frame(frm): + SwingUtilities.updateComponentTreeUI(frm) + frm.validate() + frm.repaint() +#$callSwing(update_frame, frm) + + +x=0 +for i in range(0,10000000): + x=x+1 \ No newline at end of file diff --git a/script/tools/CheckPuckDetection.py b/script/tools/CheckPuckDetection.py new file mode 100644 index 0000000..0582bad --- /dev/null +++ b/script/tools/CheckPuckDetection.py @@ -0,0 +1,6 @@ +USR,PWD = "pi", "raspberry" +HOST,PORT = "tell-raspberrypi", 22 +CMD= "sudo systemctl status puck_detection.service" + +ret = run("tools/SshExec") +set_return(ret) \ No newline at end of file diff --git a/script/tools/Math.py b/script/tools/Math.py new file mode 100644 index 0000000..c76ce33 --- /dev/null +++ b/script/tools/Math.py @@ -0,0 +1,68 @@ +################################################################################################### +# Math utilities +################################################################################################### + + +from mathutils import estimate_peak_indexes, fit_gaussians, create_fit_point_list, Gaussian +import java.awt.Color as Color + +import mathutils +mathutils.MAX_ITERATIONS = 100000 + +def fit(ydata, xdata = None, draw_plot = True): + if xdata is None: + xdata = frange(0, len(ydata), 1) + max_y= max(ydata) + index_max = ydata.index(max_y) + max_x= xdata[index_max] + #print "Max index:" + str(index_max), + #print " x:" + str(max_x), + #print " y:" + str(max_y) + + if draw_plot: + plots = plot([ydata],["data"],[xdata], title="Fit" ) + p = None if plots is None else plots[0] + + gaussians = fit_gaussians(ydata, xdata, [index_max,]) + if gaussians[0] is None: + if draw_plot and (p is not None): + p.addMarker(max_x, None, "Max="+str(round(max_x,4)), Color.GRAY) + print "Fitting error" + return (None, None, None) + + (norm, mean, sigma) = gaussians[0] + if draw_plot: + fitted_gaussian_function = Gaussian(norm, mean, sigma) + scale_x = [float(min(xdata)), float(max(xdata)) ] + points = max((len(xdata)+1), 100) + resolution = (scale_x[1]-scale_x[0]) / points + fit_y = [] + fit_x = frange(scale_x[0],scale_x[1],resolution, True) + for x in fit_x: + fit_y.append(fitted_gaussian_function.value(x)) + #Server + if p is None: + plot([ydata,fit_y],["data","fit"],[xdata,fit_x], title="Fit") + draw_plot = False + else: + p.addSeries(LinePlotSeries("fit")) + p.getSeries(1).setData(fit_x, fit_y) + + if abs(mean - xdata[index_max]) < abs((scale_x[0] + scale_x[1])/2): + if draw_plot: + p.addMarker(mean, None, "Mean="+str(round(mean,4)), Color.MAGENTA.darker()) + #print "Mean -> " + str(mean) + return (norm, mean, sigma) + else: + if draw_plot: + p.addMarker(max_x, None, "Max="+str(round(max_x,4)), Color.GRAY) + #print "Invalid gaussian fit: " + str(mean) + return (None, None, None) + + +def enforce_monotonic(x): + epsilon = 1e-8 + for i in range(len(x)-1): + if x[i+1]<=x[i]: + x[i+1] = x[i]+ epsilon + return x \ No newline at end of file diff --git a/script/tools/RestartPuckDetection.py b/script/tools/RestartPuckDetection.py new file mode 100644 index 0000000..2251921 --- /dev/null +++ b/script/tools/RestartPuckDetection.py @@ -0,0 +1,8 @@ +USR,PWD = "pi", "raspberry" +HOST,PORT = "tell-raspberrypi", 22 +CMD= "sudo systemctl stop puck_detection.service;sudo systemctl start puck_detection.service" + +ret = run("tools/SshExec") +set_return(ret) + +puck_detection.initialize() \ No newline at end of file diff --git a/script/tools/SshExec.py b/script/tools/SshExec.py new file mode 100644 index 0000000..c9e4f50 --- /dev/null +++ b/script/tools/SshExec.py @@ -0,0 +1,61 @@ +import com.jcraft.jsch.Channel as Channel +import com.jcraft.jsch.ChannelShell as ChannelShell +import com.jcraft.jsch.JSch as JSch +import com.jcraft.jsch.JSchException as JSchException +import com.jcraft.jsch.Session as Session +import java.lang.System as System +import java.io.PrintStream as PrintStream + + +#Parameters: +#CMD +#USR +#PWD +#HOST +#PORT + +jsch= JSch() +session=jsch.getSession(USR, HOST, PORT) +session.setPassword(PWD) +session.setConfig("StrictHostKeyChecking", "no") +session.connect() + +#channel=session.openChannel("shell") +#input_stream=channel.getInputStream() +#output_stream = channel.getOutputStream() +#print_stream = PrintStream(output_stream, True) +#print_stream.println("ls") + +channel=session.openChannel("exec") +channel.setCommand(CMD) +channel.setInputStream(None) +channel.setOutputStream(System.out) +channel.setErrStream(System.err) +input_stream=channel.getInputStream() + + +def wait_ret(): + global input_stream + rx = "" + while True: + while (input_stream.available() > 0): + i = input_stream.read() + if i < 0: + break + rx=rx+chr(i) + if channel.closed: + break + time.sleep(0.1) + return rx + + +channel.connect() + +try: + ret = wait_ret() +except: + channel.disconnect() + session.disconnect() + raise + +set_return(ret) \ No newline at end of file diff --git a/script/tools/StopPuckDetection.py b/script/tools/StopPuckDetection.py new file mode 100644 index 0000000..1ff6f04 --- /dev/null +++ b/script/tools/StopPuckDetection.py @@ -0,0 +1,8 @@ +USR,PWD = "pi", "raspberry" +HOST,PORT = "tell-raspberrypi", 22 +CMD= "sudo systemctl stop puck_detection.service" + +ret = run("tools/SshExec") +set_return(ret) + +

b+V|I; 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 literal 0 HcmV?d00001 diff --git a/plugins/MXSC-1.10.0.jar.back b/plugins/MXSC-1.10.0.jar.back new file mode 100644 index 0000000000000000000000000000000000000000..fa172f3e94ab63b2480eb726977028a039df3be7 GIT binary patch literal 263817 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