def test_Worker_DAQ___rate(): print_title("Worker_DAQ - INTERNAL_TIMER - DAQ rate") def DAQ_function(): # Must return True when successful, False otherwise reply = dev.fake_query_1() dprint(" " * 50 + "%.1f Hz" % qdev.obtained_DAQ_rate_Hz) return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice() qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.INTERNAL_TIMER, DAQ_function=DAQ_function, DAQ_interval_ms=10, critical_not_alive_count=1, debug=DEBUG) # fmt: on assert qdev.start() == True # Simulate device runtime start_time = time.perf_counter() while time.perf_counter() - start_time < 1.51: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() assert 9 <= qdev.obtained_DAQ_interval_ms <= 11 assert 99 <= qdev.obtained_DAQ_rate_Hz <= 101
def test_Worker_DAQ___CONTINUOUS(start_alive=True): print_title("Worker_DAQ - CONTINUOUS" + ("" if start_alive else " - start dead")) def DAQ_function(): # Must return True when successful, False otherwise time.sleep(0.1) # Simulate blocking processing time on the device reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice(start_alive=start_alive) qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ( DAQ_trigger=DAQ_TRIGGER.CONTINUOUS, DAQ_function=DAQ_function, critical_not_alive_count=1, debug=DEBUG, ) # fmt: on qdev.signal_DAQ_updated.connect(process_DAQ_updated) qdev.signal_DAQ_paused.connect(process_DAQ_paused) assert qdev.start() == start_alive # Immediately fire a call to test if the worker is ready for it qdev.unpause_DAQ() # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(300, qdev.pause_DAQ) QtCore.QTimer.singleShot(600, qdev.unpause_DAQ) QtCore.QTimer.singleShot(900, qdev.pause_DAQ) QtCore.QTimer.singleShot(1200, qdev.unpause_DAQ) while time.perf_counter() - start_time < 1.6: app.processEvents() if dev.count_commands == 12: break time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() if start_alive: assert dev.count_commands >= 10 assert dev.count_replies >= 10 assert (cnt_DAQ_updated >= 9 ) # Last signal is not always received before thread is quit assert cnt_DAQ_paused == 3
def test_Worker_DAQ___lose_connection(): print_title("Worker_DAQ - INTERNAL_TIMER - lose connection") def DAQ_function(): # Must return True when successful, False otherwise if qdev.update_counter_DAQ == 10: dev.is_alive = False reply = dev.fake_query_1() return reply[-4:] == "0101" # NOTE: The global 'go' mechanism used here is a quick and dirty way to # pytest. In production, it should be implemented by an boolean external # class member. global go go = True @QtCore.pyqtSlot() def process_connection_lost(): tprint("---> received: connection_lost") global go go = False app = create_QApplication() dev = FakeDevice() # Forcefully remove members as extra test del dev.name del dev.is_alive qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.INTERNAL_TIMER, DAQ_function=DAQ_function, DAQ_interval_ms=20, critical_not_alive_count=3, debug=DEBUG) # fmt: on qdev.create_worker_jobs(debug=DEBUG) qdev.signal_connection_lost.connect(process_connection_lost) assert qdev.start() == True # Simulate device runtime while go: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True assert qdev.quit() == True # Twice, to check for msg 'already closed'. app.quit()
def test_Worker_jobs__jobs_function(): print_title("Worker_jobs - jobs_function") def jobs_function(func, args): if func == "special command": dev.fake_query_2() else: # Default job handling where, e.g. # func = self.dev.write # args = ("toggle LED",) func(*args) app = create_QApplication() dev = FakeDevice() qdev = QDeviceIO(dev) qdev.create_worker_jobs( jobs_function=jobs_function, debug=DEBUG, ) qdev.signal_jobs_updated.connect(process_jobs_updated) assert qdev.start() == True # Immediately fire a call to test if the worker is ready for it qdev.send(dev.fake_query_2) # fmt: off # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(100, lambda: qdev.send("special command")) QtCore.QTimer.singleShot( 200, lambda: qdev.send(dev.fake_command_with_argument, 0)) # fmt: on while time.perf_counter() - start_time < 0.5: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() assert dev.count_commands == 3 assert dev.count_replies == 2 assert cnt_jobs_updated == 3
def test_Worker_jobs(start_alive=True): print_title("Worker_jobs" + ("" if start_alive else " - start dead")) app = create_QApplication() dev = FakeDevice(start_alive=start_alive) qdev = QDeviceIO(dev) qdev.create_worker_jobs(debug=DEBUG) qdev.signal_jobs_updated.connect(process_jobs_updated) assert qdev.start() == start_alive # Immediately fire a call to test if the worker is ready for it qdev.add_to_jobs_queue(dev.fake_query_2) # fmt: off # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(100, qdev.process_jobs_queue) QtCore.QTimer.singleShot(200, lambda: qdev.send(dev.fake_query_2)) QtCore.QTimer.singleShot( 300, lambda: qdev.add_to_jobs_queue(dev.fake_command_with_argument, 0)) QtCore.QTimer.singleShot( 400, lambda: qdev.add_to_jobs_queue(dev.fake_command_with_argument, 0)) QtCore.QTimer.singleShot( 500, lambda: qdev.add_to_jobs_queue(dev.fake_command_with_argument, 0)) QtCore.QTimer.singleShot(600, qdev.process_jobs_queue) QtCore.QTimer.singleShot( 700, lambda: qdev.send("trigger_illegal_function_call_error")) # fmt: on while time.perf_counter() - start_time < 1: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() if start_alive: assert dev.count_commands == 5 assert dev.count_replies == 2 assert cnt_jobs_updated == 4
def test_Worker_DAQ___SINGLE_SHOT_WAKE_UP(start_alive=True): print_title("Worker_DAQ - SINGLE_SHOT_WAKE_UP" + ("" if start_alive else " - start dead")) def DAQ_function(): # Must return True when successful, False otherwise reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice(start_alive=start_alive) qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.SINGLE_SHOT_WAKE_UP, DAQ_function=DAQ_function, critical_not_alive_count=1, debug=DEBUG) # fmt: on qdev.signal_DAQ_updated.connect(process_DAQ_updated) assert qdev.start() == start_alive # Immediately fire a call to test if the worker is ready for it qdev.wake_up_DAQ() # Simulate device runtime start_time = time.perf_counter() QtCore.QTimer.singleShot(300, qdev.wake_up_DAQ) QtCore.QTimer.singleShot(600, qdev.wake_up_DAQ) while time.perf_counter() - start_time < 1: app.processEvents() time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() if start_alive: assert dev.count_commands == 3 assert dev.count_replies == 3 assert cnt_DAQ_updated == 3
def test_Worker_DAQ___INTERNAL_TIMER(start_alive=True): print_title("Worker_DAQ - INTERNAL_TIMER" + ("" if start_alive else " - start dead")) def DAQ_function(): # Must return True when successful, False otherwise reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice(start_alive=start_alive) qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.INTERNAL_TIMER, DAQ_function=DAQ_function, DAQ_interval_ms=100, critical_not_alive_count=10, debug=DEBUG) # fmt: on qdev.signal_DAQ_updated.connect(process_DAQ_updated) assert qdev.start() == start_alive # Simulate device runtime start_time = time.perf_counter() while time.perf_counter() - start_time < 1: app.processEvents() if dev.count_commands == 3: break time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit() if start_alive: assert dev.count_commands >= 3 assert dev.count_replies >= 3 assert (cnt_DAQ_updated >= 2 ) # Last signal is not always received before thread is quit
def test_Worker_DAQ___ILLEGAL_DAQ_FUNCTION(): print_title("Worker_DAQ - ILLEGAL_DAQ_FUNCTION") def DAQ_function(): # Must return True when successful, False otherwise if qdev.update_counter_DAQ == 2: 0 / 0 else: reply = dev.fake_query_1() return reply[-4:] == "0101" app = create_QApplication() dev = FakeDevice() qdev = QDeviceIO(dev) # fmt: off qdev.create_worker_DAQ(DAQ_trigger=DAQ_TRIGGER.INTERNAL_TIMER, DAQ_function=DAQ_function, DAQ_interval_ms=100, debug=DEBUG) # fmt: on qdev.signal_DAQ_updated.connect(process_DAQ_updated) assert qdev.start() == True # Simulate device runtime start_time = time.perf_counter() while time.perf_counter() - start_time < 1: app.processEvents() if dev.count_commands == 3: break time.sleep(0.001) # Do not hog the CPU tprint("About to quit") app.processEvents() assert qdev.quit() == True app.quit()
) qdev_ard.create_worker_jobs(debug=DEBUG) # Connect signals to slots qdev_ard.signal_DAQ_updated.connect(window.update_GUI) qdev_ard.signal_connection_lost.connect(notify_connection_lost) # Hack. TODO: Implement start/stop in `QDeviceIO` def start_stop(): qdev_ard.worker_DAQ.DAQ_function = ( DAQ_function if window.qpbt_running.isChecked() else None) window.qpbt_running.clicked.connect(start_stop) # Start workers qdev_ard.start(DAQ_priority=QtCore.QThread.TimeCriticalPriority) # -------------------------------------------------------------------------- # Create plot refresh timer # -------------------------------------------------------------------------- timer_chart = QtCore.QTimer() # timer_chart.setTimerType(QtCore.Qt.PreciseTimer) timer_chart.timeout.connect(window.update_chart) timer_chart.start(CHART_INTERVAL_MS) # -------------------------------------------------------------------------- # Start the main GUI event loop # -------------------------------------------------------------------------- window.show() sys.exit(app.exec_())
# Main # ------------------------------------------------------------------------------ if __name__ == "__main__": app = QtWid.QApplication(sys.argv) app.aboutToQuit.connect(about_to_quit) window = MainWindow() # Fake a device that generates data at a sampling rate of `Fs` Hz. The # data gets generated and transferred to our HistoryChartCurve-instance from # out of a separate thread. This is taken care of by QDeviceIO. class FakeDevice: def __init__(self): self.name = "FakeDevice" self.is_alive = True qdev = QDeviceIO(dev=FakeDevice()) qdev.create_worker_DAQ(DAQ_interval_ms=WORKER_DAQ_INTERVAL_MS, DAQ_function=DAQ_function) qdev.signal_DAQ_updated.connect(window.update_GUI) qdev.start() # Chart refresh timer timer_chart = QtCore.QTimer(timerType=QtCore.Qt.PreciseTimer) timer_chart.timeout.connect(window.update_charts) timer_chart.start(CHART_DRAW_INTERVAL_MS) window.show() sys.exit(app.exec_())
log.signal_recording_started.connect( lambda filepath: window.qpbt_record.setText( "Recording to file: %s" % filepath ) ) log.signal_recording_stopped.connect( lambda: window.qpbt_record.setText("Click to start recording to file") ) # -------------------------------------------------------------------------- # Timers # -------------------------------------------------------------------------- timer_GUI = QtCore.QTimer() timer_GUI.timeout.connect(window.update_GUI) timer_GUI.start(100) timer_charts = QtCore.QTimer() timer_charts.timeout.connect(window.update_chart) timer_charts.start(CHART_INTERVAL_MS) # -------------------------------------------------------------------------- # Start the main GUI event loop # -------------------------------------------------------------------------- qdev_ard.start() qdev_julabo.start() window.show() sys.exit(app.exec_())