Как я могу записать файл построчно с pyserial в com0com? - PullRequest
1 голос
/ 19 октября 2019

Я не могу записать более одной строки данных из файла в виртуальный com-порт (com0com) с помощью pyserial. Я пытаюсь записать файл построчно, чтобы я мог одновременно обновить индикатор выполнения в Tkinter. Я работаю в Windows и попытался поместить операцию записи в свой собственный поток (для контроллера UART с Tkinter и Python GUI ). Моя программа зависает после написания одной строки.

Соответствующий код:

import os
import sys
from functools import partial
import re
import time
import threading

import serial
import serial.tools.list_ports

import tkinter as tk
from tkinter import ttk, filedialog

class MainApp(tk.Tk):

    def __init__(self,
                 parent,
                 title = 'Main Application',
                 *args,
                 **kwargs):

        self.parent = parent

        #Set window title and size
        self.parent.title(title)

        #Create widget container
        container = tk.Frame(self.parent)

        #Add widgets

        # --> Create load program widgets
        load_frame = tk.LabelFrame(container,
                                   text = 'Load Program',
                                   width = 400,
                                   height = 100)

        port_dropdown = DropDown(load_frame,
                                 label = 'Port:',
                                 row = 0)

        file_browser = Browser(load_frame,
                               path_type = 'file',
                               label = 'File:',
                               row = 1)

        program_downloader = Downloader(load_frame,
                                        port_dropdown,
                                        file_browser,
                                        row = 2)

        # --> Layout load program widgets
        load_frame.grid(row = 0,
                        column= 0,
                        padx = (5,5),
                        pady = (5,5))

        #Layout widget container
        container.pack(fill = tk.BOTH,
                       padx = 10,
                       pady = 5,
                       expand = True)         
.
.
.

class Downloader(tk.Frame):

    def __init__(self,
                 parent,
                 port_dropdown,
                 file_browser,
                 row = 0):

        self.port_dropdown = port_dropdown
        self.file_browser = file_browser

        #Instantiate serial port object
        self.serial_port = None

        self.progress_bar = ttk.Progressbar(parent,
                                            orient = 'horizontal',
                                            mode = 'determinate')

        self.progress_bar.grid(row = row,
                               column = 0,
                               columnspan = 2,
                               padx = (5,5),
                               pady = (5,5),
                               sticky = 'WE')

        self.button = tk.Button(parent,
                                text = 'Download',
                                command = self.download_program)

        self.button.grid(row = row,
                         column = 2,
                         padx = (5,5),
                         pady = (5,5),
                         sticky = 'W')

    def download_program(self):

        port_full_name = self.port_dropdown.combobox.get()
        port_name = re.match('([^\s]+)', port_full_name).group(0)

        baud_rate = 9600

        program_path = self.file_browser.text.get()

        self.connect(port_name,
                     baud_rate,
                     program_path)

    def connect(self,
                port_name,
                baud_rate,
                program_path):

        self.serial_port = serial.Serial(port_name,
                                         baud_rate,
                                         timeout=1)

        t1 = threading.Thread(target = self.transfer_data,
                              args = (program_path,))
        t1.daemon = True
        t1.start()

    def transfer_data(self,
                      program_path):

        line = 1
        self.progress_bar['value'] = line

        with open(program_path, 'r') as program:

            max_lines = len(program.readlines())
            self.progress_bar['maximum'] = max_lines

        with open(program_path, 'r') as program:

            while line < max_lines:

                command = program.readline().replace('\n','\r\n')

                print(str(line) + ': ' + repr(command))

                self.serial_port.write(command.encode('ascii'))

                line += 1

                self.progress_bar['value'] = line

                self.serial_port.flush()

        print('done')
        self.disconnect()

    def disconnect(self):
        self.serial_port.close()

if __name__ == '__main__':

    #Initialize Tkinter
    root = tk.Tk()

    #Create GUI
    gui = MainApp(root,
                  'Main Application')

    #Run program
    root.mainloop()

GUI Hangs:

GUI Output

Терминальный вывод:

1: '@01\r\n'
2: '@02\r\n'

Тот факт, что я могу читать с program.txt во второй раз в циклеговорит мне, что программа может зависать, потому что порт все еще застрял при первой записи.

Любая помощь будет оценена.

1 Ответ

0 голосов
/ 20 октября 2019

Установите timeout и write_timeout на 0 для предотвращения блокировки, которая, кажется, решает проблему.

...