Hello everyone, I am a ruffian balance, is a serious technical ruffian. Today ruffian balance to introduce you is the serial port debugging tool Pzh-py-COM birth software optimization.

Front ruffian balance has initially implemented the pZH-py-COM serial port function, and through the most basic test, but the current PZH-Py-COM compared to the market popular serial port debugging tool is far away, there is a lot of room for optimization. Optimization can be carried out from two aspects: first, it is functional optimization, can add more practical functions; Second, the optimization of the interface effect, you can add some interface animation effect or re-color beautify the interface. The following ruffian balance from these two aspects for pzh-py-COM to do some simple optimization:

First, function optimization

1.1 Enhanced robustness

Started to do the function of the optimization should be enhanced robustness of software, namely, in the case of any abnormal user input, the software can’t hang up, what value found in the measured when the user input in a “Com Port” is an invalid serial number, the software will die, so do the following improvement, when open the equipment using the try the except statement, If there is an exception, exit directly without continuing the execution of the following code. There are many more such improvements.

class mainWin(win.com_win) :

    def openClosePort( self, event ) :
        if s_serialPort.isOpen():
            s_serialPort.close()
            self.m_button_openClose.SetLabel('Open')
        else:
            #...
            self.setParitybits()
            # Add code to start
            try:
                s_serialPort.open(a)except Exception, e:
                # Show warning message
                return
            # Add code end
            self.m_button_openClose.SetLabel('Close')
            #...
Copy the code

1.2 Automatic detection of available ports

The original version implemented Port selection by manually entering the user in the standard format “COMx”, but there is a problem with this: the user may enter an invalid format, and even if a valid format is entered, it may not be a valid Port. Refer to the popular serial Port debugging assistant in the market, either select all COM ports from the drop-down menu (such as AccessPort, which can solve the problem of invalid input format), or select available COM ports from the drop-down menu (such as Sscom, which can solve the problem of whether Port is valid). Ruffian balance with reference to SSCOM approach to pZH-py-COM has been optimized as follows:

class mainWin(win.com_win) :

    def __init__(self, parent) :
        self.refreshComPort(None)
        self.m_choice_comPort.SetSelection( 0 )

    def refreshComPort( self, event ) :
        comports = list(serial.tools.list_ports.comports())
        ports = [None] * len(comports)
        for i in range(len(comports)):
            comport = list(comports[i])
            # example comport = [u'COM3', u'Intel(R) Active Management Technology - SOL (COM3)', u'PCI\\VEN_8086&DEV_9D3D&SUBSYS_06DC1028&REV_21\\3&11583659&0&B3']
            ports[i] = comport[0] + The '-' + comport[1]
        self.m_choice_comPort.Clear()
        self.m_choice_comPort.SetItems(ports)

    def setPort ( self ) :
        index = self.m_choice_comPort.GetSelection()
        comPort = self.m_choice_comPort.GetString(index)
        comPort = comPort.split(The '-')
        s_serialPort.port = comPort[0]
Copy the code

1.3 Implement the format switching function

Char/Hex Format conversion is a more practical function, the general serial port debugging helper will have this function, pzh-py-com before default always in accordance with the Char Format input and display, “Format” box function is not actually implemented, so RHP here added Format switching function.

import formatter

s_formatter = formatter.formatter()
s_lastRecvFormat = None
s_lastSendFormat = None

class mainWin(win.com_win) :

    # Function function realization
    def setSendFormat( self, event ) :
        lines = self.m_textCtrl_send.GetNumberOfLines()
        iflines ! =0:
            m_sendFormat = self.m_choice_sendFormat.GetString(self.m_choice_sendFormat.GetSelection())
            global s_lastSendFormat
            if s_lastSendFormat == m_sendFormat:
                return
            else:
                s_lastSendFormat = m_sendFormat
            # Get existing data from textCtrl_send
            data = ' '
            for i in range(0, lines):
                data += str(self.m_textCtrl_send.GetLineText(i))
            # Convert data format according to choice_sendFormat
            if m_sendFormat == 'Char':
                status, data = s_formatter.hexToChar(data)
                if not status:
                    self.m_textCtrl_send.Clear()
                    self.m_textCtrl_send.write('Invalid format! Correct example: 12 34 56 ab cd ef')
                    return
            elif m_sendFormat == 'Hex':
                data = s_formatter.charToHex(data)
            # Re-show converted data in textCtrl_send
            self.m_textCtrl_send.Clear()
            self.m_textCtrl_send.write(data)

    def sendData( self, event ) :
        if s_serialPort.isOpen():
            lines = self.m_textCtrl_send.GetNumberOfLines()
            iflines ! =0:
                data = ' '
                for i in range(0, lines):
                    data += str(self.m_textCtrl_send.GetLineText(i))
                # Add code to start
                # Make sure data is always in 'Char' format
                m_sendFormat = self.m_choice_sendFormat.GetString(self.m_choice_sendFormat.GetSelection())
                if m_sendFormat == 'Hex':
                    status, data = s_formatter.hexToChar(data)
                    if not status:
                        self.m_textCtrl_send.Clear()
                        self.m_textCtrl_send.write('Invalid format! Correct example: 12 34 56 ab cd ef')
                        return
                # Add code end
                s_serialPort.write(data)

    # Function function realization
    def setRecvFormat( self, event ) :
        lines = self.m_textCtrl_recv.GetNumberOfLines()
        iflines ! =0:
            m_recvFormat = self.m_choice_recvFormat.GetString(self.m_choice_recvFormat.GetSelection())
            global s_lastRecvFormat
            if s_lastRecvFormat == m_recvFormat:
                return
            else:
                s_lastRecvFormat = m_recvFormat
            # Get existing data from textCtrl_recv
            data = ' '
            for i in range(0, lines):
                data += str(self.m_textCtrl_recv.GetLineText(i))
            # Convert data format according to choice_recvFormat
            if m_recvFormat == 'Char':
                status, data = s_formatter.hexToChar(data)
            elif m_recvFormat == 'Hex':
                data = s_formatter.charToHex(data)
            # Re-show converted data in textCtrl_recv
            self.m_textCtrl_recv.Clear()
            self.m_textCtrl_recv.write(data)

    def recvData( self ) :
        if s_serialPort.isOpen():
            num = s_serialPort.inWaiting()
            ifnum ! =0:
                data = s_serialPort.read(num)
                # Add code to start
                # Note: Assume that data is always in 'Char' format
                # Convert data format if dispaly format is 'Hex'
                m_recvFormat = self.m_choice_recvFormat.GetString(self.m_choice_recvFormat.GetSelection())
                if m_recvFormat == 'Hex':
                    data = s_formatter.charToHex(data)
                # Add code end
                self.m_textCtrl_recv.write(data)
Copy the code

The format switching function of the send input box is tested as follows, especially in Hex mode. If there is abnormal input, pZH-py-com will clear the screen and prompt the correct example in the input box. The format switch function of the receiving display box is the same, but there is no abnormal input prompt, because this is a result display output box.

1.4 Enabling the menu bar

Menu bar is a fully functional software standard, used to achieve a variety of features, here ruffian balance only added a “Help” menu, used to display pzh-py-com home page and author information. WxFormBuilder: wxFormBuilder: wxFormBuilder: wxFormBuilder: wxFormBuilder: wxFormBuilder: wxFormBuilder: wxFormBuilder: wxFormBuilder: Menu

    def showHomepageMessage( self, event ) :
        messageText = (('Code: \n https://github.com/JayHeng/pzh-py-com.git \n') +
                       ('Doc: \n https://www.cnblogs.com/henjay724/p/9416096.html \n'))
        wx.MessageBox(messageText, "Homepage", wx.OK | wx.ICON_INFORMATION)

    def showAboutMessage( self, event ) :
        messageText = (('Author: Jay Heng \n') +
                       ('Email: [email protected] \n'))
        wx.MessageBox(messageText, "About", wx.OK | wx.ICON_INFORMATION)
Copy the code

1.5 Enabling the Status bar

Status bar is also the general serial port debugging assistant standard configuration, used to display the sending/receiving data statistics and serial port switch status, so ruffian balance for Pzh-py-com also added the status bar function, status bar is mainly divided into three columns: receiving data statistics, sending data statistics, serial port status.

s_recvStatusFieldIndex = 0
s_sendStatusFieldIndex = 1
s_infoStatusFieldIndex = 2

s_recvStatusStr = 'Recv: '
s_recvTotalBytes = 0
s_sendStatusStr = 'Send: '
s_sendTotalBytes = 0

class mainWin(win.com_win) :

    def openClosePort( self, event ) :
        if s_serialPort.isOpen():
            s_serialPort.close()
            self.m_button_openClose.SetLabel('Open')
            # Add code to start
            self.statusBar.SetStatusText(s_serialPort.name + ' is closed', s_infoStatusFieldIndex)
            # Add code end
        else:
            # Add code to start
            self.statusBar.SetFieldsCount(3)
            self.statusBar.SetStatusWidths([150.150.400])
            # Add code end
            self.setPort()
            #...
            self.m_button_openClose.SetLabel('Close')
            # Add code to start
            self.statusBar.SetStatusText(s_recvStatusStr + str(s_recvTotalBytes), s_recvStatusFieldIndex)
            self.statusBar.SetStatusText(s_sendStatusStr + str(s_sendTotalBytes), s_sendStatusFieldIndex)
            self.statusBar.SetStatusText(s_serialPort.name + ' is open, ' +
                                               str(s_serialPort.baudrate) + ', ' +
                                               str(s_serialPort.bytesizes) + ', ' +
                                               s_serialPort.parity + ', ' +
                                               str(s_serialPort.stopbits), s_infoStatusFieldIndex)
            # Add code end
            s_serialPort.reset_input_buffer()
            #...

    def sendData( self, event ) :
        if s_serialPort.isOpen():
            lines = self.m_textCtrl_send.GetNumberOfLines()
            iflines ! =0:
                #...
                s_serialPort.write(data)
                # Add code to start
                global s_sendTotalBytes
                s_sendTotalBytes += len(data)
                self.statusBar.SetStatusText(s_sendStatusStr + str(s_sendTotalBytes), s_sendStatusFieldIndex)
                # Add code end
        else:
            self.statusBar.SetStatusText(s_serialPort.name + ' is not open !!! ', s_infoStatusFieldIndex)

    def recvData( self ) :
        if s_serialPort.isOpen():
            num = s_serialPort.inWaiting()
            ifnum ! =0:
                #...
                self.m_textCtrl_recv.write(data)
                # Add code to start
                global s_recvTotalBytes
                s_recvTotalBytes += len(data)
                self.statusBar.SetStatusText(s_recvStatusStr + str(s_recvTotalBytes), s_recvStatusFieldIndex)
                # Add code end
Copy the code

The measured functions of the status bar are as follows:

Second, interface optimization

2.1 Adding the Serial Port Switch On Effect

Interface optimization there are a lot of places, ruffian balance simply made a serial switch button synchronization with the small light display effect, when the serial port is open, the small light shows green; When the serial port is off, the small light is black. The implementation in the code is actually a switch between two images.

class mainWin(win.com_win) :

    def openClosePort( self, event ) :
        if s_serialPort.isOpen():
            s_serialPort.close()
            self.m_button_openClose.SetLabel('Open')
            # Add code to start
            self.m_bitmap_led.SetBitmap(wx.Bitmap( u".. /img/led_black.png", wx.BITMAP_TYPE_ANY ))
            # Add code end
        else:
            #...
            self.m_button_openClose.SetLabel('Close')
            # Add code to start
            self.m_bitmap_led.SetBitmap(wx.Bitmap( u".. /img/led_green.png", wx.BITMAP_TYPE_ANY ))
            # Add code end
            #...
Copy the code

At this point, serial debugging tool pzh-py-com birth software optimization ruffian balance will be introduced to the end, applause where ~~~

Welcome to subscribe to

The article will be published on my blog park homepage, CSDN homepage and wechat public account platform at the same time.

Wechat search “ruffian balance embedded” or scan the following two-dimensional code, you can see the first time on the phone oh.