def main(argv): try: opts, args = getopt.getopt(argv, "hl", []) except getopt.GetoptError: print('EnsembleFileReport.py -i <inputfile> -v') sys.exit(2) for opt, arg in opts: if opt == '-h': print('test_AdcpSerialPortServer.py ') sys.exit() elif opt in ("-l"): print("Available Serial Ports:") serial_list = AdcpSerialPortServer.list_serial_ports() exit() # Start the server AdcpSerialPortServer("55056", '/dev/tty.usbserial-FT0ED8ZR', 115200)
def start_adcp_server(self): """ Start the ADCP Serial TCP server """ self.serial_server = AdcpSerialPortServer( self.get_tcp_port(), self.comm_port_combobox.currentText(), self.get_baud()) # Create an ensemble reader #self.ensemble_reader_thread = threading.Thread(name='EnsembleReader', target=EnsembleReader.EnsembleReader(self.get_tcp_port())).start() # Connect to serial server to send commands self.adcp_writer_thread = threading.Thread( name='AdcpWriter', target=self.create_raw_serial_socket(self.get_tcp_port())).start() logger.debug("start server")
def connect(self, comm_port, baud, folder_path, file_name, tcp_port=55056): """ Connect to the serial port server to receive data. :param comm_port: Comm port to connect to. :param baud: Baud Rate. :param folder_path: Folder path to store the recorded data. :param file_name: File name used to create a new file. :param tcp_port: TCP Port to receive the data. """ self.comm_port = comm_port self.baud = baud self.tcp_port = tcp_port self.folder_path = folder_path self.file_name = file_name self.serial_server = AdcpSerialPortServer(tcp_port, comm_port, baud) # Start a tcp connection to monitor incoming data and record self.serial_server_thread = threading.Thread( name='AdcpWriter', target=self.create_raw_serial_socket(self.tcp_port)) self.serial_server_thread.start()
def connect(self, rabbit_url, rabbit_user, rabbit_pw, comm_port, baud, tcp_port="55056"): # Create a RabbitMQ connection self.rabbit = rabbitmq_topic() self.rabbit.connect(exchange="ADCP", host=rabbit_url, user=rabbit_user, pw=rabbit_pw) # Create an ADCP codec self.codec = AdcpCodec() self.codec.EnsembleEvent += self.process_ensemble # Create an ADCP Serial port connection self.serial_server = AdcpSerialPortServer(tcp_port, comm_port, baud) # Start a tcp connection to monitor incoming data and record self.serial_server_thread = threading.Thread(name='AdcpWriter', target=self.create_raw_serial_socket(tcp_port)) self.serial_server_thread.start()
def main(argv): """ MAIN to run the application. """ url = "localhost" user = "******" password = "******" comm_port = "" baud=115200 try: opts, args = getopt.getopt(argv, "hu:c:p:t:b:", ["url=", "user="******"pw=", "verbose"]) except getopt.GetoptError: print('SerialEnsembleEmitter.py -u <url> -c <username> -p <password> -t <comm_port> -b <baud>') sys.exit(2) for opt, arg in opts: if opt == '-h': print('SerialEnsembleEmitter.py -u <url> -c <username> -p <password> -t <comm_port> -b <baud>') sys.exit() elif opt in ("-b", "--baud"): baud = arg elif opt in ("-t", "--port"): comm_port = arg elif opt in ("-u", "--url"): url = arg elif opt in ("-c", "--user"): user = arg elif opt in ("-p", "--password"): password = arg print('Comm Port: ', comm_port) print('Baud Rate: ', baud) print('RabbitMQ URL: ', url) print('RabbitMQ User: ', user) print("Available Serial Ports:") serial_list = AdcpSerialPortServer.list_serial_ports() # Verify a good serial port was given if comm_port in serial_list: SerialEnsembleEmitter().connect(rabbit_url=url, rabbit_user=user, rabbit_pw=password, comm_port=comm_port, baud=baud)
def main(argv): comm_port = '' baud = '115200' tcp_port = '55056' folder_path = 'recorder' verbose = False file_name = "Adcp" try: opts, args = getopt.getopt( argv, "hlvc:b:f:p:n:", ["comm=", "baud=", "folder=", "name=", "tcp=", "verbose"]) except getopt.GetoptError: print( 'SerialDataRecorder.py -c <comm> -b <baud> -f <folder> -p <tcp> -n <file_name> -v' ) sys.exit(2) for opt, arg in opts: if opt == '-h': print('usage: SerialDataRecorder.py ') print( '-c <comm>\t : Serial Comm Port. Use -l to list all the ports.' ) print('-b <baud>\t : Serial Baud Rate. Default 115200.') print( '-p <tcp>\t : TCP Port to output the serial data. Default 55056. Change if used already.' ) print( '-f <folder>\t : Folder path to store the serial data. Default is same path as application.' ) print( '-n <file_name>\t : File name for the files. Default is "Adcp.' ) print('-v\t : Verbose output.') print('Utilities:') print('-l\t : Print all available Serial Ports') sys.exit() elif opt == '-l': AdcpSerialPortServer.list_serial_ports() sys.exit() elif opt in ('-c', "--comm"): comm_port = arg elif opt in ("-b", "--baud"): baud = arg elif opt in ("-f", "--folder"): folder_path = arg elif opt in ("-p", "--tcp"): tcp_port = arg elif opt in ("-n", "--name"): file_name = arg elif opt in ("-v", "--verbose"): verbose = True print("Verbose ON") print('Comm Port: ', comm_port) print('Baud Rate: ', baud) print('TCP Port: ', tcp_port) print('Folder Path: ', folder_path) print('File Name: ', file_name) print("Available Serial Ports:") serial_list = AdcpSerialPortServer.list_serial_ports() # Verify a good serial port was given if comm_port in serial_list: # Run serial port sdr = SerialDataRecorder(verbose).connect(comm_port, baud, folder_path, file_name, tcp_port) sdr.stop_adcp_server() else: print( "----------------------------------------------------------------") print("BAD SERIAL PORT GIVEN") print("Please use -c to give a good serial port.") print("-l will give you a list of all available serial ports.")
class SerialDataRecorder: """ Record the serial data. This will work as a data logger. It will record the serial data and write it to the file path given. If no file path is given it will write it in the same directory as the application is run. """ # Max file size. 16mbs MAX_FILE_SIZE = 1048576 * 16 # Recorder File name RECORDER_FILE_NAME = "Adcp" def __init__(self, verbose=False): self.serial_server = None self.serial_server_thread = None self.comm_port = "" self.baud = 0 self.tcp_port = 0 self.verbose = verbose self.folder_path = '' self.raw_serial_socket = None self.isAlive = True self.file = None self.file_size = 0 self.file_name = self.RECORDER_FILE_NAME def connect(self, comm_port, baud, folder_path, file_name, tcp_port=55056): """ Connect to the serial port server to receive data. :param comm_port: Comm port to connect to. :param baud: Baud Rate. :param folder_path: Folder path to store the recorded data. :param file_name: File name used to create a new file. :param tcp_port: TCP Port to receive the data. """ self.comm_port = comm_port self.baud = baud self.tcp_port = tcp_port self.folder_path = folder_path self.file_name = file_name self.serial_server = AdcpSerialPortServer(tcp_port, comm_port, baud) # Start a tcp connection to monitor incoming data and record self.serial_server_thread = threading.Thread( name='AdcpWriter', target=self.create_raw_serial_socket(self.tcp_port)) self.serial_server_thread.start() def create_raw_serial_socket(self, port): """ Connect to the ADCP serial server. This TCP server outputs data from the serial port. Start reading the data. """ try: # Create a file self.create_file_writer() # Create socket self.raw_serial_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.raw_serial_socket.connect(('localhost', int(port))) self.raw_serial_socket.settimeout( 1) # Set timeout to stop thread if terminated except ConnectionRefusedError as err: logger.error("Serial Send Socket: ", err) except Exception as err: logger.error('Serial Send Socket: ", Error Opening socket', err) # Start to read the raw data self.read_tcp_socket() def read_tcp_socket(self): """ Read the data from the TCP port. This is the raw data from the serial port. Then write this data to the file. """ while self.isAlive: try: # Read data from socket data = self.raw_serial_socket.recv(4096) # If data exist process if len(data) > 0: # Write the data to the file self.file.write(data) # Keep track of the file size self.file_size += len(data) # Limit the output prompt #if self.file_size % 5 == 0: # print('.', end="", flush=True) # Check the file size to see if a new file needs to be created if self.file_size > self.MAX_FILE_SIZE: self.close_file_write() # Close this file self.create_file_writer() # Open a new file except socket.timeout: # Just a socket timeout, continue on pass except Exception as e: logger.error("Exception in reading data.", e) self.stop_adcp_server() print("Read Thread turned off") def create_file_writer(self): """ Create a file writer. This will open the file and have it ready to write data to the file. """ file_path = self.get_new_file() logger.debug("Open File name: " + file_path) self.file_size = 0 self.file = open(file_path, 'wb') def close_file_write(self): """ Close the file. """ logger.debug("Close the file") self.file.close() def get_new_file(self): """ Create a new file path. If the file exist, update the index until a new unique name is created. :return: New File name. """ index = 0 file_name = self.file_name + str(index) if not os.path.isdir(self.folder_path): os.makedirs(self.folder_path) # Create a new file name file_path = os.path.join(self.folder_path, file_name + ".ens") # Continue to create a file until a new file name is found while os.path.exists(file_path): index += 1 file_name = self.file_name + str(index) file_path = os.path.join(self.folder_path, file_name + ".ens") return file_path def stop_adcp_server(self): """ Stop the ADCP Serial TCP server """ # Stop the thread loop self.isAlive = False if self.serial_server is not None: self.serial_server.close() logger.debug("serial server stopped") else: logger.debug('No serial connection') # Close the socket self.raw_serial_socket.close() # Stop the server thread if self.serial_server_thread is not None: self.serial_server_thread.join() # Close the open file self.close_file_write() logger.debug("Stop the Recorder")
class view_serial(QtWidgets.QWidget): """ Create the QT display """ def __init__(self, parent=None): QtWidgets.QWidget.__init__(self, parent) # Global variables self.serial_server = None self.raw_serial_socket = None self.raw_serial_alive = False self.ensemble_reader_thread = None self.adcp_writer_thread = None self.serial_buffer = "" raw_serial_tcp_port = settings.get('SerialServerSection', 'RawSerialTcpPort') ens_udp_port = settings.get('SerialServerSection', 'JsonEnsUdpPort') # QT GUI self.tcp_port_combobox = QtWidgets.QComboBox() self.tcp_port_combobox.setEditable(True) self.tcp_port_combobox.addItems([raw_serial_tcp_port, ""]) self.ens_udp_port_combobox = QtWidgets.QComboBox() self.ens_udp_port_combobox.setEditable(True) self.ens_udp_port_combobox.addItems([ens_udp_port, ""]) self.comm_port_combobox = QtWidgets.QComboBox() self.comm_port_combobox.addItems(self.serial_ports()) self.comm_baud_combobox = QtWidgets.QComboBox() self.comm_baud_combobox.setEditable(True) self.comm_baud_combobox.addItems(["921600", "115200", "19200", ""]) self.comm_baud_combobox.setCurrentIndex(1) connect = QtWidgets.QPushButton("Connect") connect.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) connect.clicked.connect(self.start_adcp_server) disconnect = QtWidgets.QPushButton("Reconnect") disconnect.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) disconnect.clicked.connect(self.reconnect_adcp_server) self.command_txtbox = QtWidgets.QLineEdit() send_cmd_btn = QtWidgets.QPushButton("Send") #send_cmd_btn.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) send_cmd_btn.clicked.connect(self.send_cmd_adcp_server) send_break_btn = QtWidgets.QPushButton("BREAK") #send_break_btn.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) send_break_btn.clicked.connect(self.send_break_adcp_server) #quit = QtWidgets.QPushButton("Quit") #quit.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) #self.connect(quit, QtCore.SIGNAL("clicked()"), # QtWidgets.qApp, QtCore.SLOT("quit()")) self.serial_txtbox = QtWidgets.QTextEdit() self.serial_txtbox.setMinimumHeight(500) clear_btn = QtWidgets.QPushButton("Clear") #send_break_btn.setFont(QtGui.QFont("Times", 18, QtGui.QFont.Bold)) clear_btn.clicked.connect(self.clear_serial) # Add Widgets gridLayout = QtWidgets.QGridLayout() gridLayout.addWidget(self.tcp_port_combobox, 0, 0) gridLayout.addWidget(self.ens_udp_port_combobox, 0, 1) gridLayout.addWidget(self.comm_port_combobox, 1, 0) gridLayout.addWidget(self.comm_baud_combobox, 1, 1) gridLayout.addWidget(connect, 2, 0) gridLayout.addWidget(disconnect, 2, 1) gridLayout.addWidget(self.command_txtbox, 3, 0) gridLayout.addWidget(send_cmd_btn, 3, 1) gridLayout.addWidget(send_break_btn, 3, 2) gridLayout.addWidget(self.serial_txtbox, 4, 0, 2, 3) # row, cl, rs, cs gridLayout.addWidget(clear_btn, 5, 2) # Set Spacing #gridLayout.setColumnStretch(1, 10) gridLayout.setRowStretch(4, 20) # Add Menu #self.createMenu() #gridLayout.setMenuBar(self.createMenu()) gridLayout.addWidget(self.createMenu()) # Set Window attributes self.setLayout(gridLayout) self.setWindowTitle("Echo - RoweTech Inc.") def createMenu(self): menuBar = QtWidgets.QMenuBar() fileMenu = QtWidgets.QMenu("File") exitAction = fileMenu.addAction("E&xit") menuBar.addMenu(fileMenu) #exitAction.triggered.connect(self.exit) return menuBar def closeEvent(self, event): """ Override the close event for the QWidget. If a serial port is open, close the connection. """ logger.debug('Closing serial') self.stop_adcp_server() # Close window event.accept() def start_adcp_server(self): """ Start the ADCP Serial TCP server """ self.serial_server = AdcpSerialPortServer( self.get_tcp_port(), self.comm_port_combobox.currentText(), self.get_baud()) # Create an ensemble reader #self.ensemble_reader_thread = threading.Thread(name='EnsembleReader', target=EnsembleReader.EnsembleReader(self.get_tcp_port())).start() # Connect to serial server to send commands self.adcp_writer_thread = threading.Thread( name='AdcpWriter', target=self.create_raw_serial_socket(self.get_tcp_port())).start() logger.debug("start server") def create_raw_serial_socket(self, port): """ Connect to the ADCP serial server. """ try: self.raw_serial_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.raw_serial_socket.connect(('localhost', int(port))) self.raw_serial_socket.settimeout( 1) # Set timeout to stop thread if terminated except ConnectionRefusedError as err: logger.error("Serial Send Socket: ", err) except Exception as err: logger.error('Serial Send Socket: ", Error Opening socket', err) # Start a thread to read the raw data self.ensemble_reader_thread = ReadRawSerialThread( self.raw_serial_socket, int(self.ens_udp_port_combobox.currentText())) self.ensemble_reader_thread.raw_data.connect(self.on_raw_read) self.ensemble_reader_thread.start() @QtCore.Slot(object) def on_raw_read(self, data): """ Buffer up the data received from the serial port from the TCP server. Then set it to the text. :param data: Data received from the TCP server which came from the serial port. """ try: self.serial_buffer += bytes(data).decode() except Exception as err: #print("error decoding", err) # Decoding does not work for the binary data, only commands self.serial_buffer += str(data).strip() # Chop off the top portion of the message slicer = slice(-1130, None) self.serial_buffer = self.serial_buffer[slicer] # Set the text to the textbox self.serial_txtbox.setText(self.serial_buffer) def stop_adcp_server(self): """ Stop the ADCP Serial TCP server """ if self.serial_server is not None: self.serial_server.close() logger.debug("serial server stopped") else: logger.debug('No serial connection') # Close the socket self.raw_serial_socket.close() if self.adcp_writer_thread is not None: self.adcp_writer_thread.join() if self.ensemble_reader_thread is not None: #self.ensemble_reader_thread.terminate() #self.ensemble_reader_thread.setTerminationEnabled(True) self.ensemble_reader_thread.stop() def send_cmd_adcp_server(self): """ Send the command to the socket """ # Get the command from the txtbox cmd = self.command_txtbox.text().strip() # Encode the data to byte array and send to socket self.raw_serial_socket.send((cmd.strip()).encode()) def send_break_adcp_server(self): """ Send the BREAK command to the socket """ cmd = "BREAK" # Encode the data to byte array and send to socket self.raw_serial_socket.send((cmd.strip()).encode("utf-16")) def reconnect_adcp_server(self): """ Reconnect the serial port connection with the new settings. """ logger.debug("reconnect") cmd = "RECONNECT, " + self.comm_port_combobox.currentText( ) + "," + self.comm_baud_combobox.currentText() # Encode the data to byte array and send to socket self.raw_serial_socket.send((cmd.strip()).encode("utf-16")) def get_baud(self): """ Convert the baud rate from string to int. If an error, set the baud rate to 115200 :returns: baud rate """ try: baud = int(self.comm_baud_combobox.currentText()) except Exception as err: logger.error("Error setting baud rate: ", err) self.comm_baud_combobox.setCurrentIndex(1) return "115200" return baud def get_tcp_port(self): """ Convert the TCP port from string to int. If an error, set the default port to 55056 :returns: TCP Port """ try: port = int(self.tcp_port_combobox.currentText()) except Exception as err: logger.error("Error setting TCP Port: ", err) self.tcp_port_combobox.setCurrentIndex(0) return "55056" return str(port) def clear_serial(self): """ Clear the serial port display. """ # Set the text to the textbox self.serial_txtbox.setText("") def find_port(self): """ Finds available port for Tornado / Flask :return: Available port :rtype: int """ port_attempts = 0 while port_attempts < 1000: try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(('localhost', 0)) app_port = sock.getsockname()[1] sock.close() logger.debug("PORT: " + str(app_port)) return app_port except Exception as err: port_attempts += 1 logger.error(err) logger.error("FAILED AFTER 1000 PORT ATTEMPTS") sys.exit(1)