def start(self): """ Starts all processes, based on configuration given in constructor. :return: """ self.reset_buffers(self._samples) if self._export: self._csv_process = CSVProcess(path=self._path) self._parser_process = ParserProcess( self._queue, store_reference=self._csv_process) else: self._parser_process = ParserProcess(self._queue) if self._source == SourceType.serial: self._acquisition_process = SerialProcess(self._parser_process) elif self._source == SourceType.simulator: self._acquisition_process = SimulatorProcess(self._parser_process) if self._acquisition_process.open(port=self._port, speed=self._speed): self._parser_process.start() if self._export: self._csv_process.start() self._acquisition_process.start() return True else: Log.i(TAG, "Port is not available") return False
def stop(self): """ Signals the process to stop acquiring data. :return: """ Log.i(TAG, "Process finishing...") self._exit.set()
def open(self, host='', port=45454, timeout=0.01): """ Opens a socket connection to specified host and port :param host: Host address to connect to. :type host: str. :param port: Port number to connect to. :type port: int. :param timeout: Sets timeout for socket interactions. :type timeout: float. :return: True if the connection was open. :rtype: bool. """ try: # self._socket_server.timeout = timeout port = int(port) self._socket_server.bind((host, port)) Log.i(TAG, "Socket open {}:{}".format(host, port)) print("listening on {}:{}".format( self._socket_server.getsockname()[0], self._socket_server.getsockname()[1])) self._socket_server.listen(1) self._conn, address = self._socket_server.accept() self._conn.setblocking(0) # non-blocking print("accepted from {}".format(address)) return True except socket.timeout: Log.w(TAG, "Connection timeout") return False
def _update_sample_size(self): """ Updates the sample size of the plot. This function is connected to the valueChanged signal of the sample Spin Box. :return: """ if self.worker is not None: Log.i(TAG, "Changing sample size") self.worker.reset_buffers(self.ui.sBox_Samples.value())
def stop(self): """ Signals the process to stop acquiring data. :return: """ Log.i(TAG, "Server closing") self._conn.close() self._socket_server.close() self._exit.set()
def closeEvent(self, evnt): """ Overrides the QTCloseEvent. This function is connected to the clicked signal of the close button of the window. :param evnt: QT evnt. :return: """ if self.worker.is_running(): Log.i(TAG, "Window closed without stopping capture, stopping it") self.stop()
def stop(self): """ Stops the acquisition of the selected serial port. This function is connected to the clicked signal of the Stop button. :return: """ Log.i(TAG, "Clicked stop") self._timer_plot.stop() self._enable_ui(True) self.worker.stop()
def __init__(self, parser_process): """ Initialises values for process. :param parser_process: Reference to a ParserProcess instance. :type parser_process: ParserProcess """ multiprocessing.Process.__init__(self) self._exit = multiprocessing.Event() self._parser = parser_process self._socket_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) Log.i(TAG, "Process Ready")
def __init__(self, parser_process): """ Initialises values for process. :param parser_process: Reference to a ParserProcess instance. :type parser_process: ParserProcess. """ multiprocessing.Process.__init__(self) self._exit = multiprocessing.Event() self._parser = parser_process self._serial = serial.Serial() Log.i(TAG, "Process ready")
def run(self): """ Simulates raw data incoming as CSV. :return: """ Log.i(TAG, "Process starting...") timestamp = time() coef = 2 * np.pi while not self._exit.is_set(): stamp = time() - timestamp self._parser.add([stamp, str(("{},{}\r\n".format(np.sin(coef * stamp), np.cos(coef * stamp)))) .encode(Constants.app_encoding)]) sleep(self._period) Log.i(TAG, "Process finished")
def reset_buffers(self, samples): """ Setup/clear the internal buffers. :param samples: Number of samples for the buffers. :type samples: int. :return: """ self._data_buffers = [] for tmp in Constants.plot_colors: self._data_buffers.append(RingBuffer(samples)) self._time_buffer = RingBuffer(samples) while not self._queue.empty(): self._queue.get() Log.i(TAG, "Buffers cleared")
def __init__(self, parser_process): """ Initialises values for process. :param parser_process: Reference to a ParserProcess instance. :type parser_process: ParserProcess """ multiprocessing.Process.__init__(self) self._exit = multiprocessing.Event() self._parser = parser_process self._socket_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self._socket_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self._conn = None Log.i(TAG, "Process Ready")
def open(self, port=None, speed=Constants.simulator_default_speed, timeout=0.5): """ Opens a specified serial port. :param port: Not used. :type port: str. :param speed: Period of the generated signal. :type speed: float. :param timeout: Not used. :type timeout: float. :return: True if the port is available. :rtype: bool. """ self._period = float(speed) Log.i(TAG, "Using sample rate at {}".format(self._period)) return True
def run(self): if Architecture.is_python_version(MinimalPython.major, minor=MinimalPython.minor): Log.i(TAG, "Starting RTGraph") win = mainWindow.MainWindow(samples=self._args.get_user_samples()) win.setWindowTitle("{} - {}".format(Constants.app_title, Constants.app_version)) win.show() self._app.exec() Log.i(TAG, "Finishing RTGraph\n") win.close() else: self._fail() self.close()
def run(self): """ Process will monitor the internal buffer to write data to the export file, and the process will loop again after timeout if more data is available. :return: """ Log.i(TAG, "Process starting...") self._csv = csv.writer(self._file, delimiter=Constants.csv_delimiter, quoting=csv.QUOTE_MINIMAL) while not self._exit.is_set(): self._consume_queue() sleep(self._timeout) # last check on the queue to completely remove data. self._consume_queue() Log.i(TAG, "Process finished") self._file.close()
def run(self): """ Reads the socket until a stop call is made. :return: """ Log.i(TAG, "Process starting...") timestamp = time() while not self._exit.is_set(): stamp = time() - timestamp try: data = self._socket_client.recv( Constants.SocketClient.buffer_recv_size).decode() if len(data) > 0: self._parser.add([stamp, data]) except socket.timeout: Log.w(TAG, "read timeout") Log.i(TAG, "Process finished")
def _source_changed(self): """ Updates the source and depending boxes on change. This function is connected to the indexValueChanged signal of the Source ComboBox. :return: """ Log.i(TAG, "Scanning source {}".format(self._get_source().name)) # clear boxes before adding new self.ui.cBox_Port.clear() self.ui.cBox_Speed.clear() source = self._get_source() ports = self.worker.get_source_ports(source) speeds = self.worker.get_source_speeds(source) self.ui.cBox_Port.addItems(ports) self.ui.cBox_Speed.addItems(speeds) self.ui.cBox_Speed.setCurrentIndex(len(speeds) - 1)
def _create_file(filename, path=None, extension=Constants.csv_extension): """ Creates the file to export the data. :param filename: Name of the file where data will be exported. :type filename: str. :param path: Path where data file will be saved. :type path: str. :param extension: Extension to give to the export file. :type extension: str. :return: Reference to the export file. """ FileManager.create_dir(path) full_path = FileManager.create_file(filename, extension=extension, path=path) if not FileManager.file_exists(full_path): Log.i(TAG, "Storing in {}".format(full_path)) return open(full_path, "a", newline='') return None
def start(self): """ Starts the acquisition of the selected serial port. This function is connected to the clicked signal of the Start button. :return: """ Log.i(TAG, "Clicked start") self.worker = Worker(port=self.ui.cBox_Port.currentText(), speed=float(self.ui.cBox_Speed.currentText()), samples=self.ui.sBox_Samples.value(), source=self._get_source(), export_enabled=self.ui.chBox_export.isChecked()) if self.worker.start(): self._timer_plot.start(Constants.plot_update_ms) self._enable_ui(False) else: Log.i(TAG, "Port is not available") PopUp.warning(self, Constants.app_title, "Selected port \"{}\" is not available" .format(self.ui.cBox_Port.currentText()))
def run(self): """ Reads the socket until a stop call is made OR client disconnects. :return: """ Log.i(TAG, "Process starting...") while not self._exit.is_set(): try: # this is set to non-blocking so we can catch errors if no data is present packet = self._conn.recv( Constants.SocketServer.buffer_recv_size).decode() if len(packet) > 0: # executed by the other process? self._parser.add(packet) else: # client no longer sending data Log.w(TAG, "No incoming data") self.stop() except BlockingIOError: # connection being establish pass Log.i(TAG, "Process finished")
def open(self, port='', speed=45454, timeout=0.01): """ Opens a socket connection to specified host and port :param port: Host address to connect to. :type port: str. :param speed: Port number to connect to. :type speed: int. :param timeout: Sets timeout for socket interactions. :type timeout: float. :return: True if the connection was open. :rtype: bool. """ try: #self._socket_client.timeout = timeout speed = int(speed) self._socket_client.connect((port, speed)) Log.i(TAG, "Socket open {}:{}".format(port, speed)) return True except socket.timeout: Log.w(TAG, "Connection timeout") return False
def __init__(self, filename=None, path=None, timeout=0.5): """ Sets up the file to export the data as CSV. If filename is not specified, a default name based on time will be used. :param filename: Name of the file where data will be exported. :type filename: str. :param path: Path where data file will be saved. :type path: str. :param timeout: Time to wait after emptying the internal buffer before next write. :type timeout: float. """ multiprocessing.Process.__init__(self) self._exit = multiprocessing.Event() self._store_queue = multiprocessing.Queue() self._csv = None self._file = None self._timeout = timeout if filename is None: filename = strftime(Constants.csv_default_filename, gmtime()) self._file = self._create_file(filename, path=path) Log.i(TAG, "Process ready")
def run(self): """ Reads the serial port expecting CSV until a stop call is made. The expected format is comma (",") separated values, and a new line (CRLF or LF) as a new row. While running, it will parse CSV data convert each value to float and added to a queue. If incoming data from serial port can't be converted to float, that data will be discarded. :return: """ Log.i(TAG, "Process starting...") if self._is_port_available(self._serial.port): if not self._serial.isOpen(): self._serial.open() Log.i(TAG, "Port opened") timestamp = time() while not self._exit.is_set(): self._parser.add( [time() - timestamp, self._serial.readline()]) Log.i(TAG, "Process finished") self._serial.close() else: Log.w(TAG, "Port is not opened") else: Log.w(TAG, "Port is not available")