You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

srv_controller.py 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. #!/bin/python3
  2. import threading, sys, time, queue
  3. from puppeteer import Controller, HardwareTest, TemperatureTest,\
  4. ProtocolTest, ExportData, QueueStatus, CancelProtocol,\
  5. CameraRepetitions
  6. from pupuicon import InitNetwork, NetworkOperator
  7. # Hack
  8. # FIXME: Does it mean `translator have should it's own package?.
  9. sys.modules['translator'] = sys.modules['pupuicon.translator']
  10. del sys.modules['pupuicon.translator']
  11. # Create `cancel' and `gui' switches. Default to FALSE.
  12. cancel_switch = threading.Event()
  13. gui_status = threading.Event()
  14. protocol_status = threading.Event()
  15. # Check for presence of queueFile after restarting LiMO, set `protocol_status'
  16. # accordingly:
  17. Replicates, LagReplicates = CameraRepetitions()
  18. while True:
  19. try:
  20. print("GUI status is: " + str(gui_status.is_set()))
  21. # Set server-side
  22. Box_Socket = InitNetwork(PORT=10011, MAX_CONNECTIONS=1)
  23. # Wait here until connection happens.
  24. gui_status.set() # GUI status -> TRUE, user connected.
  25. print("GUI status is now: " + str(gui_status.is_set()))
  26. while True:
  27. if protocol_status.is_set():
  28. print("Protocol finished, but data not retrieved.")
  29. if cancel_switch.is_set():
  30. cancel_switch.clear()
  31. GUI = NetworkOperator(Box_Socket.Connection, BUFFER_SIZE=64) # Buffer in bytes.
  32. # Create a new thread (box hardware independent of everything else).
  33. # Box_Socket can still be populated in parallel (i.e. to cancel protocol).
  34. try:
  35. if GUI.command.__module__ == 'pupuicon.translator._core':
  36. USR_INSTRUCTIONS = GUI.command
  37. if len(USR_INSTRUCTIONS.QueueTimes) > 1:
  38. # This is a normal protocol...
  39. BoxQueue = queue.Queue()
  40. Box = threading.Thread(target=Controller, args=(USR_INSTRUCTIONS,
  41. Box_Socket.Connection,
  42. cancel_switch,
  43. gui_status,
  44. BoxQueue,
  45. protocol_status))
  46. Box.start()
  47. [LiMO, Protocol, QueueFile] = BoxQueue.get()
  48. elif len(USR_INSTRUCTIONS.QueueTimes) == 1:
  49. # This is a grab...
  50. print("User says: (Flexi)grab data.")
  51. BoxQueue = queue.Queue()
  52. Box = threading.Thread(target=Controller, args=(USR_INSTRUCTIONS,
  53. Box_Socket.Connection,
  54. cancel_switch,
  55. gui_status,
  56. BoxQueue,
  57. protocol_status))
  58. Box.start()
  59. [_, Protocol, _] = BoxQueue.get()
  60. Box.join() # Wait until thread finishes (1 step only).
  61. ExportData(Protocol, False, None, Box_Socket.Connection,
  62. gui_status, Test=True)
  63. protocol_status.clear()
  64. except AttributeError:
  65. # __module__ attribute does not exist, therefore
  66. # GUI.command does not contain a protocol.
  67. print("User says: " + GUI.command + ".")
  68. if GUI.command == "Close Connection":
  69. Box_Socket.Socket.close()
  70. break
  71. elif GUI.command == "Test Hardware":
  72. print("Testing hardware...")
  73. HardwareTest(Box_Socket.Connection, gui_status)
  74. elif GUI.command == "Test Temperature":
  75. print("Testing heater...")
  76. TemperatureTest(Box_Socket.Connection, gui_status)
  77. elif GUI.command == "Test Protocol":
  78. print("Running test protocol...")
  79. Protocol = ProtocolTest(Box_Socket.Connection,
  80. cancel_switch, gui_status)
  81. ExportData(Protocol, False, False,
  82. Box_Socket.Connection, gui_status, Test=True)
  83. elif GUI.command == "Abort Protocol":
  84. # Turn hardware OFF before cancelling!! otherwise things
  85. # like HEATER can be left ON.
  86. Box._stop()
  87. Box.join()
  88. print("Cancel Protocol.")
  89. if 'LiMO' in locals():
  90. CancelProtocol(with_device=LiMO)
  91. else:
  92. # This steps allows to restart LiMO without anything running.
  93. CancelProtocol()
  94. elif GUI.command == "Check Queue":
  95. try:
  96. if Protocol:
  97. print("Checking Queue...")
  98. QueueStatus(QueueFile, Box_Socket.Connection) # Assumes `Protocol' exists. Greyed-out in GUI.
  99. except NameError:
  100. print("No protocol running.")
  101. pass
  102. elif GUI.command == "Retrieve data": # Assumes `Protocol' exists. Greyed-out in GUI.
  103. ExportData(Protocol, False, QueueFile,
  104. Box_Socket.Connection, gui_status)
  105. protocol_status.clear()
  106. else:
  107. # GUI _always_ expects something coming back.
  108. # By returning a message, the interface won't stall.
  109. Box_Socket.Connection.sendall(str("::IDLE::").encode())
  110. except (ConnectionResetError, BrokenPipeError, OSError) as err: # This will forever (unsuccessfully) try to start server
  111. Box_Socket.Socket.close()
  112. print("GUI status was: " + str(gui_status.is_set()))
  113. gui_status.clear() # GUI status -> FALSE, disconnect user.
  114. print("GUI status is now: " + str(gui_status.is_set()))
  115. print(err)
  116. print("\nRestarting server.")
  117. """
  118. TODO:
  119. - Implement logs to deal with potential problems reported by users. [DONE]
  120. - Export data when process_data=False (send over network) [TODO: issues with threading...] [DONE]
  121. - Retrieve Queue and initiate protocol automatically if LiMO's power breaks. [DONE]
  122. MISSING FIELDS in LIF file:
  123. - panel_type (guess from 'nmwavelengthsOfFiltersInstalled'?)
  124. - device calibration
  125. - number of wells
  126. - well calibration
  127. - protocol name (guess from 'readsDirectory'?) [NOT NEEDED]
  128. - notes [NOT NEEDED]
  129. - export metadata [DONE/ NOT NEEDED]
  130. """