zoukankan      html  css  js  c++  java
  • 串口调试工具(Python2.7+pyserial+Tkinter)

    需要与串口设备进行通讯,那么一个调试工具是必须的。

    根据我自己的需要,写了个简易版本的串口调试工具:

    预览图:

    ======================

    项目结构:

    COM

    --SerialHelper.py

    UI

    --Adaptive.py

    --SerialTool.py

    --PyTkinter.py

    main.py

    ======================

    COM文件夹

    SerialHelper.py 串口通讯帮助类

     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 
     4 '''
     5 Serial设备通讯帮助类
     6 '''
     7 __author__ = "jakey.chen"
     8 __version__ = "v1.0"
     9 
    10 import sys
    11 import threading
    12 import time
    13 import serial
    14 import binascii
    15 import logging
    16 
    17 class SerialHelper(object):
    18     def __init__(self, Port="COM6", BaudRate="9600", ByteSize="8", Parity="N", Stopbits="1"):
    19         '''
    20         初始化一些参数
    21         '''
    22         self.l_serial = None
    23         self.alive = False
    24         self.port = Port
    25         self.baudrate = BaudRate
    26         self.bytesize = ByteSize
    27         self.parity = Parity
    28         self.stopbits = Stopbits
    29         self.thresholdValue = 64
    30         self.receive_data = ""
    31 
    32     def start(self):
    33         '''
    34         开始,打开串口
    35         '''
    36         self.l_serial = serial.Serial()
    37         self.l_serial.port = self.port
    38         self.l_serial.baudrate = self.baudrate
    39         self.l_serial.bytesize = int(self.bytesize)
    40         self.l_serial.parity = self.parity
    41         self.l_serial.stopbits = int(self.stopbits)
    42         self.l_serial.timeout = 2
    43         
    44         try:
    45             self.l_serial.open()
    46             if self.l_serial.isOpen():
    47                 self.alive = True
    48         except Exception as e:
    49             self.alive = False
    50             logging.error(e)
    51 
    52     def stop(self):
    53         '''
    54         结束,关闭串口
    55         '''
    56         self.alive = False
    57         if self.l_serial.isOpen():
    58             self.l_serial.close()
    59 
    60     def read(self):
    61         '''
    62         循环读取串口发送的数据
    63         '''
    64         while self.alive:
    65             try:
    66                 number = self.l_serial.inWaiting()
    67                 if number:
    68                     self.receive_data += self.l_serial.read(number).replace(binascii.unhexlify("00"), "")
    69                     if self.thresholdValue <= len(self.receive_data):
    70                         self.receive_data = ""
    71             except Exception as e:
    72                 logging.error(e)
    73 
    74     def write(self, data, isHex=False):
    75         '''
    76         发送数据给串口设备
    77         '''
    78         if self.alive:
    79             if self.l_serial.isOpen():
    80                 if isHex:
    81                     # data = data.replace(" ", "").replace("
    ", "")
    82                     data = binascii.unhexlify(data)
    83                 self.l_serial.write(data)
    84 
    85 if __name__ == '__main__':
    86     import threading
    87     ser = SerialHelper()
    88     ser.start()
    89 
    90     ser.write("123", isHex=False)
    91     thread_read = threading.Thread(target=ser.read)
    92     thread_read.setDaemon(True)
    93     thread_read.start()
    94     import time
    95     time.sleep(25)
    96     ser.stop()
    View Code

    ======================

    UI文件夹

    Adaptive.py 防止错位

     1 #! /usr/bin/env python
     2 # -*- coding: utf-8 -*-
     3 
     4 import platform
     5 
     6 g_systemName = platform.system()
     7 g_systemInfo = platform.platform()
     8 g_pyVersion = platform.python_version()
     9 size_dict = dict()
    10 
    11 # System will be Linux and python == 2.7
    12 if g_systemName == "Linux" and g_pyVersion[:3] == "2.7":
    13     if "Ubuntu" in g_systemInfo:
    14         size_dict = {
    15                         "list_box_height": 20,
    16                         "send_text_height": 12,
    17                         "receive_text_height": 15,
    18                         "reset_label_width": 24,
    19                         "clear_label_width": 22
    20                     }
    21 
    22     # raspberry pi
    23     elif "armv6l" in g_systemInfo:
    24         size_dict = {
    25                         "list_box_height": 19,
    26                         "send_text_height": 12,
    27                         "receive_text_height": 15,
    28                         "reset_label_width": 24,
    29                         "clear_label_width": 22
    30                     }
    31 else:
    32     if g_systemInfo[:9]== "Windows-8":
    33         size_dict = {
    34                         "list_box_height": 14,
    35                         "send_text_height": 6,
    36                         "receive_text_height": 18,
    37                         "reset_label_width": 7,
    38                         "clear_label_width": 5
    39                      }
    40 
    41     elif g_systemInfo[:9]== "Windows-7":
    42         size_dict = {
    43                         "list_box_height": 13,
    44                         "send_text_height": 12,
    45                         "receive_text_height": 15,
    46                         "reset_label_width": 7,
    47                         "clear_label_width": 5
    48                      }
    49 
    50     elif g_systemInfo[:10]== "Windows-XP":
    51         size_dict = {
    52                         "list_box_height": 20,
    53                         "send_text_height": 12,
    54                         "receive_text_height": 22,
    55                         "reset_label_width": 7,
    56                         "clear_label_width": 5
    57                      }
    58 
    59 # font
    60 monaco_font = ('Monaco', 12)
    View Code

    PyTkinter.py 根据个人喜好来初始化一些Tkinter控件的颜色配置

      1 #! /usr/bin/env python
      2 # -*- coding: utf-8 -*-
      3 
      4 '''
      5 Tkinter控件初始化配置(默认为深色)
      6 '''
      7 __author__ = "jakey.chen"
      8 __version__ = "v1.0"
      9 
     10 
     11 import Tkinter as tk
     12 
     13 g_default_theme = "dark"
     14 # g_default_theme = "default"
     15 
     16 class PyButton(tk.Button):
     17     '''
     18     Button
     19     '''
     20     def __init__(self, master, theme=g_default_theme, **kv):
     21         self.theme = theme
     22         self.kv = kv
     23         self.temp = dict()
     24         self.choose_theme()
     25         tk.Button.__init__(self, master, self.temp)
     26 
     27     def choose_theme(self):
     28         if self.theme == "dark":
     29             dark_theme_dict = {
     30                                 "activebackground": "#00B2EE",
     31                                 "activeforeground": "#E0EEEE",
     32                                 "bg": "#008B8B",
     33                                 "fg": "#FFFFFF"
     34                               }
     35             for key,value in dark_theme_dict.items():
     36                 self.temp[key] = value
     37 
     38             for key,value in self.kv.items():
     39                 self.temp[key] = value
     40 
     41 class PyLabel(tk.Label):
     42     '''
     43     Label
     44     '''
     45     def __init__(self, master, theme=g_default_theme, **kv):
     46         self.theme = theme
     47         self.kv = kv
     48         self.temp = dict()
     49         self.choose_theme()
     50         tk.Label.__init__(self, master, self.temp)
     51 
     52     def choose_theme(self):
     53         if self.theme == "dark":
     54             dark_theme_dict = {
     55                                 "bg": "#292929",
     56                                 "fg": "#E0EEEE"
     57                               }
     58             for key,value in dark_theme_dict.items():
     59                 self.temp[key] = value
     60 
     61             for key,value in self.kv.items():
     62                 self.temp[key] = value
     63 
     64 class PyLabelFrame(tk.LabelFrame):
     65     '''
     66     Frame
     67     '''
     68     def __init__(self, master, theme=g_default_theme, **kv):
     69         self.theme = theme
     70         self.kv = kv
     71         self.temp = dict()
     72         self.choose_theme()
     73         tk.LabelFrame.__init__(self, master, self.temp)
     74 
     75     def choose_theme(self):
     76         if self.theme == "dark":
     77             dark_theme_dict = {
     78                                 "bg": "#292929",
     79                                 "fg": "#1E90FF"
     80                               }
     81             for key,value in dark_theme_dict.items():
     82                 self.temp[key] = value
     83 
     84             for key,value in self.kv.items():
     85                 self.temp[key] = value
     86 
     87 class PyListbox(tk.Listbox):
     88     '''
     89     Listbox
     90     '''
     91     def __init__(self, master, theme=g_default_theme, **kv):
     92         self.theme = theme
     93         self.kv = kv
     94         self.temp = dict()
     95         self.choose_theme()
     96         tk.Listbox.__init__(self, master, self.temp)
     97 
     98     def choose_theme(self):
     99         if self.theme == "dark":
    100             dark_theme_dict = {
    101                                 "bg": "#292929",
    102                                 "fg": "#1E90FF",
    103                                 "selectbackground": "#00B2EE"
    104                               }
    105             for key,value in dark_theme_dict.items():
    106                 self.temp[key] = value
    107 
    108             for key,value in self.kv.items():
    109                 self.temp[key] = value
    110 
    111 class PyText(tk.Text):
    112     '''
    113     Text
    114     '''
    115     def __init__(self, master, theme=g_default_theme, **kv):
    116         self.theme = theme
    117         self.kv = kv
    118         self.temp = dict()
    119         self.choose_theme()
    120         tk.Text.__init__(self, master, self.temp)
    121 
    122     def choose_theme(self):
    123         if self.theme == "dark":
    124             dark_theme_dict = {
    125                                 "bg": "#292929",
    126                                 "fg": "#1E90FF"
    127                               }
    128             for key,value in dark_theme_dict.items():
    129                 self.temp[key] = value
    130 
    131             for key,value in self.kv.items():
    132                 self.temp[key] = value
    133 
    134 class PyCheckbutton(tk.Checkbutton):
    135     '''
    136     Checkbutton
    137     '''
    138     def __init__(self, master, theme=g_default_theme, **kv):
    139         self.theme = theme
    140         self.kv = kv
    141         self.temp = dict()
    142         self.choose_theme()
    143         tk.Checkbutton.__init__(self, master, self.temp)
    144 
    145     def choose_theme(self):
    146         if self.theme == "dark":
    147             dark_theme_dict = {
    148                                 "bg": "#292929",
    149                                 "fg": "#FFFFFF",
    150                                 "activebackground": "#292929",
    151                                 "activeforeground": "#FFFFFF",
    152                                 "selectcolor": "#292929"
    153                               }
    154             for key,value in dark_theme_dict.items():
    155                 self.temp[key] = value
    156 
    157             for key,value in self.kv.items():
    158                 self.temp[key] = value
    159 
    160 class PyRadiobutton(tk.Radiobutton):
    161     '''
    162     Radiobutton
    163     '''
    164     def __init__(self, master, theme=g_default_theme, **kv):
    165         self.theme = theme
    166         self.kv = kv
    167         self.temp = dict()
    168         self.choose_theme()
    169         tk.Radiobutton.__init__(self, master, self.temp) 
    170 
    171     def choose_theme(self):
    172         if self.theme == "dark":
    173             dark_theme_dict = {
    174                                 "bg": "#292929",
    175                                 "fg": "#FFFFFF",
    176                                 "activebackground": "#292929",
    177                                 "selectcolor": "#292929"
    178                               }
    179             for key,value in dark_theme_dict.items():
    180                 self.temp[key] = value
    181 
    182             for key,value in self.kv.items():
    183                 self.temp[key] = value
    184 
    185 
    186 class PyEntry(tk.Entry):
    187     '''
    188     Entry
    189     '''
    190     def __init__(self, master, theme=g_default_theme, **kv):
    191         self.theme = theme
    192         self.kv = kv
    193         self.temp = dict()
    194         self.choose_theme()
    195         tk.Entry.__init__(self, master, self.temp)
    196 
    197     def choose_theme(self):
    198         if self.theme == "dark":
    199             dark_theme_dict = {
    200                                 "bg": "#292929",
    201                                 "fg": "#E0EEEE",
    202                                 "insertbackground": "#E0EEEE"
    203                               }
    204             for key,value in dark_theme_dict.items():
    205                 self.temp[key] = value
    206 
    207             for key,value in self.kv.items():
    208                 self.temp[key] = value
    209 
    210 if __name__ == '__main__':
    211     root = tk.Tk()
    212     root.configure(bg="#292929")
    213     PyButton(root, text="1234", font=("Monaco", 12)).pack()
    214     PyLabel(root, text="123", font=("Monaco", 15)).pack()
    215     PyCheckbutton(root, text="123", font=("Monaco", 15)).pack()
    216     PyEntry(root, font=("Monaco", 15)).pack()
    217     PyText(root, font=("Monaco", 15), height=2, width=20).pack()
    218     listbox_0 = PyListbox(root, height=2, font=("Monaco", 15))
    219     listbox_0.pack()
    220     for i in range(2):
    221         listbox_0.insert("end", i)
    222     radio_intvar = tk.IntVar()
    223     PyRadiobutton(root, text="001", variable=radio_intvar, value=0, font=("Monaco", 15)).pack()
    224     PyRadiobutton(root, text="002", variable=radio_intvar, value=1, font=("Monaco", 15)).pack()
    225     radio_intvar.set(1)
    226 
    227     root.mainloop()
    View Code

    SerialTool.py 主界面

      1 #! /usr/bin/env python
      2 # -*- coding: utf-8 -*-
      3 
      4 import Tkinter as tk
      5 import ttk
      6 import PyTkinter as pytk
      7 import Adaptive
      8 
      9 font = Adaptive.monaco_font
     10 size_dict = Adaptive.size_dict
     11 g_default_theme = pytk.g_default_theme
     12 
     13 
     14 class SerialToolUI(object):
     15     def __init__(self, master=None):
     16         self.root = master
     17         self.create_frame()
     18         self.thresholdValue = 1
     19 
     20     def create_frame(self):
     21         '''
     22         新建窗口,分为上下2个部分,下半部分为状态栏
     23         '''
     24         self.frm = pytk.PyLabelFrame(self.root)
     25         self.frm_status = pytk.PyLabelFrame(self.root)
     26 
     27         self.frm.grid(row=0, column=0, sticky="wesn")
     28         self.frm_status.grid(row=1, column=0, sticky="wesn")
     29 
     30         self.create_frm()
     31         self.create_frm_status()
     32 
     33     def create_frm(self):
     34         '''
     35         上半部分窗口分为左右2个部分
     36         '''
     37         self.frm_left = pytk.PyLabelFrame(self.frm)
     38         self.frm_right = pytk.PyLabelFrame(self.frm)
     39 
     40         self.frm_left.grid(row=0, column=0, padx=5, pady=5, sticky="wesn")
     41         self.frm_right.grid(row=0, column=1, padx=5, pady=5, sticky="wesn")
     42 
     43         self.create_frm_left()
     44         self.create_frm_right()
     45 
     46     def create_frm_left(self):
     47         '''
     48         上半部分左边窗口:
     49         Listbox显示可用的COM口
     50         Button按钮点击连接设备
     51         '''
     52         self.frm_left_label = pytk.PyLabel(self.frm_left, 
     53                                            text="Serial Ports",
     54                                            font=font)
     55         self.frm_left_listbox = pytk.PyListbox(self.frm_left,
     56                                                height=size_dict["list_box_height"],
     57                                                font=font)
     58         self.frm_left_serial_set = pytk.PyLabelFrame(self.frm_left)
     59         self.frm_left_btn = pytk.PyButton(self.frm_left, 
     60                                           text="Open",
     61                                           font=font,
     62                                           command=self.Toggle)
     63 
     64         self.frm_left_label.grid(row=0, column=0, padx=5, pady=5, sticky="w")
     65         self.frm_left_listbox.grid(row=1, column=0, padx=5, pady=5, sticky="wesn")
     66         self.frm_left_serial_set.grid(row=2, column=0, padx=5, pady=5, sticky="wesn")
     67         self.frm_left_btn.grid(row=3, column=0, padx=5, pady=5, sticky="wesn")
     68 
     69         self.frm_left_listbox.bind("<Double-Button-1>", self.Open)
     70         self.create_frm_left_serial_set()
     71 
     72     def create_frm_left_serial_set(self):
     73         '''
     74         串口配置,比如波特率,奇偶校验等
     75         '''
     76         setting_label_list = ["BaudRate :", "Parity :", "DataBit :", "StopBit :"]
     77         baudrate_list = ["1200", "2400", "4800", "9600", "14400", "19200", "38400",
     78                          "43000", "57600", "76800", "115200", "12800"]
     79         # PARITY_NONE, PARITY_EVEN, PARITY_ODD PARITY_MARK, PARITY_SPACE
     80         parity_list = ["N", "E", "O", "M", "S"]
     81         bytesize_list = ["5", "6", "7", "8"]
     82         stopbits_list = ["1", "1.5", "2"]
     83         for index,item in enumerate(setting_label_list):
     84             frm_left_label_temp = pytk.PyLabel(self.frm_left_serial_set, 
     85                                                text=item,
     86                                                font=('Monaco', 10))
     87             frm_left_label_temp.grid(row=index, column=0, padx=1, pady=2, sticky="e")
     88         self.frm_left_combobox_baudrate = ttk.Combobox(self.frm_left_serial_set,
     89                                                        width=15,
     90                                                        values=baudrate_list)
     91         self.frm_left_combobox_parity = ttk.Combobox(self.frm_left_serial_set,
     92                                                        width=15,
     93                                                        values=parity_list)
     94         self.frm_left_combobox_databit = ttk.Combobox(self.frm_left_serial_set,
     95                                                        width=15,
     96                                                        values=bytesize_list)
     97         self.frm_left_combobox_stopbit = ttk.Combobox(self.frm_left_serial_set,
     98                                                        width=15,
     99                                                        values=stopbits_list)
    100         self.frm_left_combobox_baudrate.grid(row=0, column=1, padx=2, pady=2, sticky="e")
    101         self.frm_left_combobox_parity.grid(row=1, column=1, padx=2, pady=2, sticky="e")
    102         self.frm_left_combobox_databit.grid(row=2, column=1, padx=2, pady=2, sticky="e")
    103         self.frm_left_combobox_stopbit.grid(row=3, column=1, padx=2, pady=2, sticky="e")
    104 
    105         self.frm_left_combobox_baudrate.current(3)
    106         self.frm_left_combobox_parity.current(0)
    107         self.frm_left_combobox_databit.current(3)
    108         self.frm_left_combobox_stopbit.current(0)
    109 
    110     def create_frm_right(self):
    111         '''
    112         上半部分右边窗口:
    113         分为4个部分:
    114         1、Label显示和重置按钮和发送按钮
    115         2、Text显示(发送的数据)
    116         3、Label显示和十六进制选择显示和清除接收信息按钮
    117         4、Text显示接收到的信息
    118         '''
    119         self.frm_right_reset = pytk.PyLabelFrame(self.frm_right)
    120         self.frm_right_send = pytk.PyText(self.frm_right,
    121                                           width=50, 
    122                                           height=size_dict["send_text_height"],
    123                                           font=("Monaco", 9))
    124         self.frm_right_clear = pytk.PyLabelFrame(self.frm_right)
    125         self.frm_right_receive = pytk.PyText(self.frm_right,
    126                                              width=50, 
    127                                              height=size_dict["receive_text_height"],
    128                                              font=("Monaco", 9))
    129 
    130         self.frm_right_reset.grid(row=0, column=0, padx=1, sticky="wesn")
    131         self.frm_right_send.grid(row=1, column=0, padx=1, sticky="wesn")
    132         self.frm_right_clear.grid(row=2, column=0, padx=1, sticky="wesn")
    133         self.frm_right_receive.grid(row=3, column=0, padx=1, sticky="wesn")
    134 
    135         self.frm_right_receive.tag_config("green", foreground="#228B22")
    136 
    137         self.create_frm_right_reset()
    138         self.create_frm_right_clear()
    139 
    140     def create_frm_right_reset(self):
    141         '''
    142         1、Label显示和重置按钮和发送按钮
    143         '''
    144         self.frm_right_reset_label = pytk.PyLabel(self.frm_right_reset,
    145                                                   text="Data Send" + " "*size_dict["reset_label_width"],
    146                                                   font=font)
    147         self.new_line_cbtn_var = tk.IntVar()
    148         self.send_hex_cbtn_var = tk.IntVar()
    149         self.frm_right_reset_newLine_checkbtn = pytk.PyCheckbutton(self.frm_right_reset,
    150                                                                    text="New Line",
    151                                                                    variable=self.new_line_cbtn_var,
    152                                                                    font=font)
    153         self.frm_right_reset_hex_checkbtn = pytk.PyCheckbutton(self.frm_right_reset,
    154                                                                text="Hex",
    155                                                                variable=self.send_hex_cbtn_var,
    156                                                                font=font)
    157         self.frm_right_reset_btn = pytk.PyButton(self.frm_right_reset, 
    158                                                  text="Reset",
    159                                                  width=10,
    160                                                  font=font,
    161                                                  command=self.Reset)
    162         self.frm_right_send_btn = pytk.PyButton(self.frm_right_reset, 
    163                                                 text="Send",
    164                                                 width=10,
    165                                                 font=font,
    166                                                 command=self.Send)
    167 
    168         self.frm_right_reset_label.grid(row=0, column=0, sticky="w")
    169         self.frm_right_reset_newLine_checkbtn.grid(row=0, column=1, sticky="wesn")
    170         self.frm_right_reset_hex_checkbtn.grid(row=0, column=2, sticky="wesn")
    171         self.frm_right_reset_btn.grid(row=0, column=3, padx=5, pady=5, sticky="wesn")
    172         self.frm_right_send_btn.grid(row=0, column=4, padx=5, pady=5, sticky="wesn")
    173 
    174     def create_frm_right_clear(self):
    175         '''
    176         3、Label显示和十六进制显示和清除接收信息按钮
    177         '''
    178         self.receive_hex_cbtn_var = tk.IntVar()
    179         self.frm_right_clear_label = pytk.PyLabel(self.frm_right_clear,
    180                                                   text="Data Received"+ " "*size_dict["clear_label_width"],
    181                                                   font=font)
    182         self.frm_right_threshold_label = pytk.PyLabel(self.frm_right_clear,
    183                                                       text="Threshold:",
    184                                                       font=font)
    185         self.thresholdStr = tk.StringVar()
    186         self.frm_right_threshold_entry = pytk.PyEntry(self.frm_right_clear,
    187                                                       textvariable=self.thresholdStr,
    188                                                       width=6,
    189                                                       font=font)
    190         self.frm_right_hex_checkbtn = pytk.PyCheckbutton(self.frm_right_clear,
    191                                                          text="Hex",
    192                                                          variable=self.receive_hex_cbtn_var,
    193                                                          relief="flat",
    194                                                          font=font)
    195         self.frm_right_clear_btn = pytk.PyButton(self.frm_right_clear, 
    196                                                  text="Clear",
    197                                                  width=10,
    198                                                  font=font,
    199                                                  command=self.Clear)
    200 
    201         self.frm_right_clear_label.grid(row=0, column=0, padx=5, pady=5, sticky="w")
    202         self.frm_right_threshold_label.grid(row=0, column=1, padx=5, pady=5, sticky="wesn")
    203         self.frm_right_threshold_entry.grid(row=0, column=2, padx=5, pady=5, sticky="wesn")
    204         self.frm_right_hex_checkbtn.grid(row=0, column=3, padx=5, pady=5, sticky="wesn")
    205         self.frm_right_clear_btn.grid(row=0, column=4, padx=5, pady=5, sticky="wesn")
    206 
    207         self.thresholdStr.set(1)
    208         self.thresholdStr.trace('w', self.GetThresholdValue)
    209 
    210     def create_frm_status(self):
    211         '''
    212         下半部分状态栏窗口
    213         '''
    214         self.frm_status_label = pytk.PyLabel(self.frm_status, 
    215                                              text="Ready",
    216                                              font=font)
    217         self.frm_status_label.grid(row=0, column=0, padx=5, pady=5, sticky="wesn")
    218 
    219     def Toggle(self):
    220         pass
    221 
    222     def Open(self, event):
    223         pass
    224 
    225     def Reset(self):
    226         self.frm_right_send.delete("0.0", "end")
    227 
    228     def Send(self):
    229         pass
    230 
    231     def Clear(self):
    232         self.frm_right_receive.delete("0.0", "end")
    233 
    234     def GetThresholdValue(self, *args):
    235         try:
    236             self.thresholdValue = int(self.thresholdStr.get())
    237         except:
    238             pass
    239 
    240 
    241 if __name__ == '__main__':
    242     '''
    243     main loop
    244     '''
    245     root = tk.Tk()
    246     if g_default_theme == "dark":
    247         root.configure(bg="#292929")
    248         combostyle = ttk.Style()
    249         combostyle.theme_use('alt')
    250         combostyle.configure("TCombobox", selectbackground="#292929", fieldbackground="#292929",
    251                                           background="#292929", foreground="#FFFFFF")
    252     root.title("Serial-Tool")
    253     SerialToolUI(master=root)
    254     root.resizable(False, False)
    255     root.mainloop()
    View Code

    ======================

    界面逻辑主程序

    main.py

      1 #! /usr/bin/env python
      2 # -*- coding: utf-8 -*-
      3 
      4 import time
      5 import datetime
      6 import threading
      7 import binascii
      8 import platform
      9 import logging
     10 
     11 from UI import SerialTool
     12 from COM import SerialHelper
     13 
     14 if platform.system() == "Windows":
     15     from  serial.tools import list_ports
     16 elif platform.system() == "Linux":
     17     import glob, os, re
     18 
     19 import Tkinter as tk
     20 import ttk
     21 
     22 logging.basicConfig(level=logging.DEBUG,
     23                     format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
     24                     datefmt='%a, %d %b %Y %H:%M:%S')
     25 
     26 class MainSerialToolUI(SerialTool.SerialToolUI):
     27     def __init__(self, master=None):
     28         super(MainSerialToolUI, self).__init__()
     29         self.ser = None
     30         self.receive_count = 0
     31         self.receive_data = ""
     32         self.list_box_serial = list()
     33         self.find_all_serial()
     34 
     35     def __del__(self):
     36         if platform.system() == "Linux":
     37             try:
     38                 self.ser.SetStopEvent()
     39             except:
     40                 pass
     41 
     42     def find_all_serial(self):
     43         '''
     44         获取到串口列表
     45         '''
     46         if platform.system() == "Windows":
     47             try:
     48                 self.temp_serial = list()
     49                 for com in list_ports.comports():
     50                     strCom = com[0] + ": " + com[1][:-7].decode("gbk").encode("utf-8")
     51                     self.temp_serial.append(strCom)
     52                 for item in self.temp_serial:
     53                     if item not in self.list_box_serial:
     54                         self.frm_left_listbox.insert("end", item)
     55                 for item in self.list_box_serial:
     56                     if item not in self.temp_serial:
     57                         index = list(self.frm_left_listbox.get(0, self.frm_left_listbox.size())).index(item)
     58                         self.frm_left_listbox.delete(index)
     59 
     60                 self.list_box_serial = self.temp_serial
     61 
     62                 self.thread_findserial = threading.Timer(1, self.find_all_serial)
     63                 self.thread_findserial.setDaemon(True)
     64                 self.thread_findserial.start()
     65             except Exception as e:
     66                 logging.error(e)
     67         elif platform.system() == "Linux":
     68             try:
     69                 self.temp_serial = list()
     70                 self.temp_serial = self.find_usb_tty()
     71                 for item in self.temp_serial:
     72                     if item not in self.list_box_serial:
     73                         self.frm_left_listbox.insert("end", item)
     74                 for item in self.list_box_serial:
     75                     if item not in self.temp_serial:
     76                         index = list(self.frm_left_listbox.get(0, self.frm_left_listbox.size())).index(item)
     77                         self.frm_left_listbox.delete(index)
     78                 self.list_box_serial = self.temp_serial
     79 
     80                 self.thread_findserial = threading.Timer(1, self.find_all_serial)
     81                 self.thread_findserial.setDaemon(True)
     82                 self.thread_findserial.start()
     83             except Exception as e:
     84                 logging.error(e)
     85 
     86     def Toggle(self):
     87         '''
     88         打开关闭串口
     89         '''
     90         if self.frm_left_btn["text"] == "Open":
     91             try:
     92                 self.currentStrCom = self.frm_left_listbox.get(self.frm_left_listbox.curselection())
     93                 if platform.system() == "Windows":
     94                     self.port = self.currentStrCom.split(":")[0]
     95                 elif platform.system() == "Linux":
     96                     self.port = self.currentStrCom
     97                 self.baudrate = self.frm_left_combobox_baudrate.get()
     98                 self.parity = self.frm_left_combobox_parity.get()
     99                 self.databit = self.frm_left_combobox_databit.get()
    100                 self.stopbit = self.frm_left_combobox_stopbit.get()
    101                 self.ser = SerialHelper.SerialHelper(Port=self.port,
    102                                                      BaudRate=self.baudrate,
    103                                                      ByteSize=self.databit,
    104                                                      Parity=self.parity,
    105                                                      Stopbits=self.stopbit)
    106                 self.ser.start()
    107                 if self.ser.alive:
    108                     self.frm_status_label["text"] = "Open [{0}] Successful!".format(self.currentStrCom)
    109                     self.frm_status_label["fg"] = "#66CD00"
    110                     self.frm_left_btn["text"] = "Close"
    111                     self.frm_left_btn["bg"] = "#F08080"
    112 
    113                     self.thread_read = threading.Thread(target=self.SerialRead)
    114                     self.thread_read.setDaemon(True)
    115                     self.thread_read.start()
    116 
    117             except Exception as e:
    118                 logging.error(e)
    119                 try:
    120                     self.frm_status_label["text"] = "Open [{0}] Failed!".format(self.currentStrCom)
    121                     self.frm_status_label["fg"] = "#DC143C"
    122                 except Exception as ex:
    123                     logging.error(ex)
    124 
    125         elif self.frm_left_btn["text"] == "Close":
    126             try:
    127                 self.ser.stop()
    128                 self.receive_count = 0
    129             except Exception as e:
    130                 logging.error(e)
    131             self.frm_left_btn["text"] = "Open"
    132             self.frm_left_btn["bg"] = "#008B8B"
    133             self.frm_status_label["text"] = "Close Serial Successful!"
    134             self.frm_status_label["fg"] = "#8DEEEE"
    135 
    136     def Open(self, event):
    137         '''
    138         双击列表打开/关闭串口
    139         '''
    140         self.Toggle()
    141 
    142     def Clear(self):
    143         self.frm_right_receive.delete("0.0", "end")
    144         self.receive_count = 0
    145 
    146     def Send(self):
    147         '''
    148         向已打开的串口发送数据
    149         如果为Hex发送,示例:"31 32 33" [即为字符串 "123"]
    150         '''
    151         if self.ser:
    152             try:
    153                 # 发送新行
    154                 if self.new_line_cbtn_var.get() == 0:
    155                     send_data = str(self.frm_right_send.get("0.0", "end").encode("gbk")).strip()
    156                 else:
    157                     send_data = str(self.frm_right_send.get("0.0", "end")).strip() + "
    "  
    158                 
    159                 # 是否十六进制发送
    160                 if self.send_hex_cbtn_var.get() == 1:
    161                     self.ser.write(send_data, isHex=True)
    162                 else:
    163                     self.ser.write(send_data)
    164             except Exception as e:
    165                 self.frm_right_receive.insert("end", str(e) + "
    ")
    166                 logging.error(e)
    167 
    168     def SerialRead(self):
    169         '''
    170         线程读取串口发送的数据
    171         '''
    172         while self.ser.alive:
    173             try:
    174                 n = self.ser.l_serial.inWaiting()
    175                 if n:
    176                     self.receive_data += self.ser.l_serial.read(n).replace(binascii.unhexlify("00"), "")
    177                     if self.thresholdValue <= len(self.receive_data):
    178                         self.receive_count += 1
    179 
    180                         # 接收显示是否为Hex
    181                         if self.receive_hex_cbtn_var.get() == 1:
    182                             self.receive_data = self.space_b2a_hex(self.receive_data)
    183                         self.frm_right_receive.insert("end", "[" + str(datetime.datetime.now()) + " - "
    184                                                       + str(self.receive_count) + "]:
    ", "green")
    185                         self.frm_right_receive.insert("end", self.receive_data + "
    ")
    186                         self.frm_right_receive.see("end")
    187                         self.receive_data = ""
    188 
    189             except Exception as e:
    190                 logging.error(e)
    191                 self.receive_data = ""
    192                 self.ser.stop()
    193                 self.ser = None
    194 
    195     def find_usb_tty(self, vendor_id=None, product_id=None):
    196         '''
    197         发现串口设备
    198         '''
    199         tty_devs = list()
    200         for dn in glob.glob('/sys/bus/usb/devices/*') :
    201             try:
    202                 vid = int(open(os.path.join(dn, "idVendor" )).read().strip(), 16)
    203                 pid = int(open(os.path.join(dn, "idProduct")).read().strip(), 16)
    204                 if  ((vendor_id is None) or (vid == vendor_id)) and ((product_id is None) or (pid == product_id)) :
    205                     dns = glob.glob(os.path.join(dn, os.path.basename(dn) + "*"))
    206                     for sdn in dns :
    207                         for fn in glob.glob(os.path.join(sdn, "*")) :
    208                             if  re.search(r"/ttyUSB[0-9]+$", fn) :
    209                                 tty_devs.append(os.path.join("/dev", os.path.basename(fn)))
    210             except Exception as ex:
    211                 pass
    212         return tty_devs
    213 
    214     def space_b2a_hex(self, data):
    215         '''
    216         格式化接收到的数据字符串
    217         示例:123 --> 31 32 33
    218         '''
    219         new_data_list = list()
    220         new_data = ""
    221 
    222         hex_data = binascii.b2a_hex(data)
    223         temp_data = ""
    224         for index,value in enumerate(hex_data): 
    225             temp_data += value
    226             if len(temp_data) == 2:
    227                 new_data_list.append(temp_data)
    228                 temp_data = ""
    229         for index,value in enumerate(new_data_list):
    230             if index%25 == 0 and index != 0:
    231                 new_data += "
    "
    232             new_data += value
    233             new_data += " "
    234 
    235         return new_data
    236 
    237 if __name__ == '__main__':
    238     '''
    239     main loop
    240     '''
    241     root = tk.Tk()
    242     root.title("Serial Tool")
    243     if SerialTool.g_default_theme == "dark":
    244         root.configure(bg="#292929")
    245         combostyle = ttk.Style()
    246         combostyle.theme_use('alt')
    247         combostyle.configure("TCombobox", selectbackground="#292929", fieldbackground="#292929",
    248                                           background="#292929", foreground="#FFFFFF")
    249     MainSerialToolUI(master=root)
    250     root.resizable(False, False)
    251     root.mainloop()
    View Code

    项目地址:Serial-Tool

    仅根据自己需要写的串口工具,需要其他功能的话请自行添加,或者告知我添加。

  • 相关阅读:
    基于CSS 和JS的网页SELECT下拉框美化,JQUERY 插件
    ini文件读写
    Hibernate 表关系描述之OneToMany
    Hibernate 表关系描述之ManyToMany
    Hibernate 初识
    Hibernate 表关系描述之OneToOne
    Struts配置文件初解
    Hibernate 初识(补充)
    struts 学习之04 "模型"
    (Struts)Action类及其相关类
  • 原文地址:https://www.cnblogs.com/jakeyChen/p/4465281.html
Copyright © 2011-2022 走看看