基于PYQT的MQTT协议测试工具

这段时间公司有个项目使用到了MQTT的协议与智能硬件终端进行通信,需要对通讯协议进行验证,正好这段时间一直在研究PYQT,正好写个GUI小工具,给测试组的同事们使用

主界面
主界面主要实现Publish和Subscribe 消息订阅和发送,使用了PAHO的mqtt库,我这边主要是实现了一个界面的封装
基于PYQT的MQTT协议测试工具_第1张图片

设置界面
设置界面主要是使用了python自带的sqlite数据库保存用户连接MQTT服务器时的一些个性化参数,用户可以对自己的保存的连接进行个性化命名,选中相应的连接,点击ok即可
基于PYQT的MQTT协议测试工具_第2张图片

基于PYQT的MQTT协议测试工具_第3张图片

整个小工具去掉库文件,自己实现的代码在1000行左右,只是一个初级版本,其中ConfigDialog.py就是设置页面编码,mtest.py是主界面的编码,mqttimage文件是一些图片的集合,对PYQT不是很了解的同学可以去查阅一下相关资料。

上代码
ConfigDialog.py

from PyQt4 import QtCore, QtGui
import random, mqttimage
import sqlite3, sys, os
# from PyQt4.QtGui import *  
# from PyQt4.QtCore import *  
from PyQt4.Qt import QMessageBox, QRegExpValidator


QtCore.QTextCodec.setCodecForTr(QtCore.QTextCodec.codecForName("utf8"))
childlist=[] 
user=''
class ConfigDialog(QtGui.QDialog):
    def __init__(self, parent=None):
        super(ConfigDialog, self).__init__(parent)
        self.setWindowFlags(QtCore.Qt.Window) #设置最大化最小化按钮
        self.setWindowTitle(self.tr("设置"))
        self.resize(800,450)    
        QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Cleanlooks'))#设置整体风格
        QtGui.QApplication.setPalette(QtGui.QApplication.style().standardPalette())#设置整体风格
        mainSplitter = QtGui.QSplitter(QtCore.Qt.Horizontal,self)

        amendPushButton = QtGui.QPushButton(self.tr("OK"))
        closePushButton = QtGui.QPushButton(self.tr("Cancel"))
        self.applyPushButton = QtGui.QPushButton(self.tr("Save"))
        self.applyPushButton.setDisabled(True)# 初始化save不可用
        buttonLayout = QtGui.QHBoxLayout()
        buttonLayout.addStretch(9)
        buttonLayout.addWidget(self.applyPushButton)
        buttonLayout.addWidget(amendPushButton)
#         buttonLayout.addWidget(closePushButton)  

        addButton = QtGui.QPushButton(self.tr(""))
        addButton.setFlat(True)
        addButton.setIcon(QtGui.QIcon(":img/image/plus.png"))   
        delButton = QtGui.QPushButton(self.tr(""))
        delButton.setFlat(True)          
        delButton.setIcon(QtGui.QIcon(":img/image/minus.png")) 
        buttonLayout1 = QtGui.QGridLayout()
        buttonLayout1.addWidget(addButton,0,0)
        buttonLayout1.addWidget(delButton,0,2)  


        self.treeWidget = QtGui.QTreeWidget()
        self.treeWidget.setColumnCount(1)#设置列数1
        self.treeWidget.setHeaderLabels([self.tr("Connections")])

        self.root= QtGui.QTreeWidgetItem(self.treeWidget)
        self.root.setText(0,self.tr("Profile"))
        self.treeWidget.expandAll() #节点全部展开
        treeLayout = QtGui.QVBoxLayout()
        treeLayout.addWidget(self.treeWidget)
        treeLayout.addLayout(buttonLayout1)

        self.Param1 = Param()
        rightQSplitter = QtGui.QFrame(mainSplitter)    
        stack = QtGui.QStackedWidget()
        stack.setFrameStyle(QtGui.QFrame.Panel|QtGui.QFrame.Raised)
        stack.addWidget(self.Param1)

        mainLayout_1 = QtGui.QHBoxLayout()   
        mainLayout_1.addLayout(treeLayout)
        mainLayout_1.addWidget(stack)        


        mainLayout = QtGui.QVBoxLayout(rightQSplitter)
        mainLayout.setMargin(1)
        mainLayout.setSpacing(6)      
        mainLayout.addLayout(mainLayout_1)

        Layout = QtGui.QVBoxLayout()
        Layout.addWidget(mainSplitter)
        Layout.addLayout(buttonLayout)
        self.setLayout(Layout)
        self.initDB()#初始化数据库     



        '''槽函数'''
        amendPushButton.clicked.connect(self.accept)
        closePushButton.clicked.connect(self.reject)
        self.applyPushButton.clicked.connect(self.apply)
        addButton.clicked.connect(self.add)
        delButton.clicked.connect(self.delete)
        self.connect(self.treeWidget, QtCore.SIGNAL("itemClicked(QTreeWidgetItem*,int)"),self.data_query) 
        ''''''   

    def getsetdata(self):
        self.ProfileName = self.Param1.nameEdit.text()
        self.Host = self.Param1.HostEdit.text()
        self.portValue = self.Param1.portSpinbox.value()
        self.keepValue = self.Param1.keepaliveSpinbox.value()
        self.client = self.Param1.ClientEdit.text()
        self.user = self.Param1.tab.gen.UserEdit.text()
        self.password = self.Param1.tab.gen.PassWordEdit.text()
        self.visionValue = self.Param1.tab.gen.visionComboBox.currentText()
        self.cleanssionValue = self.Param1.tab.gen.CleanSessionComboBox.currentText()
        if self.cleanssionValue =='True':
            self.cleanssion = True
#             print self.cleanssion
        else:
            self.cleanssion = False
#             print self.cleanssion
        self.napsBooL = self.Param1.tab.gen.groupBox.isChecked()#namepassword 框是否勾选
        self.pascheck = self.Param1.tab.gen.checkBox1.checkState() 
        return  self.ProfileName, self.Host, self.portValue, self.keepValue, self.client, self.user, self.password, self.visionValue,  self.cleanssion, self.napsBooL, self.pascheck


    def data_query(self, QTreeWidgetItem, int):
        global rot
        parent = QTreeWidgetItem.parent()
        if parent == -1:
            return 1
        elif parent == None:
            self.Param1.nameEdit.setText('')
            self.Param1.HostEdit.setText('')
            self.Param1.portSpinbox.setValue(0)
            self.Param1.keepaliveSpinbox.setValue(0)
            self.Param1.ClientEdit.setText('')
            self.Param1.tab.gen.UserEdit.setText('')
            self.Param1.tab.gen.PassWordEdit.setText('')
            self.applyPushButton.setDisabled(True)
        else:
            try:
                rot = parent.indexOfChild(QTreeWidgetItem)
                self.applyPushButton.setDisabled(False)
            except AttributeError:
                pass
            cur = self.conn.cursor()
            cur.execute('SELECT * FROM MQ')
            self.MQData = cur.fetchall()
            cur.execute('SELECT * FROM MQ1')
            self.MQData1 = cur.fetchall()
            cur.close()
            self.idname = childlist[rot].text(0)
    #         print childlist[rot].text(0)
            self.index = len(self.MQData)
            self.index1 = len(self.MQData1)
            if self.index > 0 :
                for x in range(self.index):
                    if self.MQData[x][0] == self.idname:
                        self.Param1.nameEdit.setText(self.idname)
                        self.Param1.HostEdit.setText(self.MQData[x][1])
                        self.Param1.portSpinbox.setValue(self.MQData[x][2])
                        self.Param1.keepaliveSpinbox.setValue(self.MQData[x][3])
                        self.Param1.ClientEdit.setText(self.MQData[x][4])
                        self.Param1.tab.gen.UserEdit.setText(self.MQData[x][5])
                        self.Param1.tab.gen.PassWordEdit.setText(self.MQData[x][6])
                        if self.MQData[x][7] == 'True':
                            self.Param1.tab.gen.CleanSessionComboBox.setCurrentIndex(0)
                        else:
                            self.Param1.tab.gen.CleanSessionComboBox.setCurrentIndex(1)
                        if self.MQData[x][8] == 'V3.1':
                            self.Param1.tab.gen.visionComboBox.setCurrentIndex(0)
                        else:
                            self.Param1.tab.gen.visionComboBox.setCurrentIndex(1)   
                        if self.MQData[x][9] == True:
                            self.Param1.tab.gen.groupBox.setChecked(True)
                        else:
                            self.Param1.tab.gen.groupBox.setChecked(False)
            if self.index1 > 0 :
                for x in range(self.index1):
                    if self.MQData1[x][0] == self.idname:
                        if self.MQData1[x][1] == 2:
                            self.Param1.tab.gen.checkBox1.setChecked(True)
                        else:
                            self.Param1.tab.gen.checkBox1.setChecked(False)  
                        self.Param1.tab.tls.openFileNameLabel.setText(self.MQData1[x][2])


#         print type(rot)
#         print rot


    @staticmethod
    def data(parent = None):
        dialog = ConfigDialog(parent)
        result = dialog.exec_()
        data = dialog.x()
        return (data, result == ConfigDialog.Accepted)

    def apply(self):
        self.name = self.Param1.nameEdit.text()
        self.host = self.Param1.HostEdit.text()
        self.portValue = self.Param1.portSpinbox.value()
        self.keepValue = self.Param1.keepaliveSpinbox.value()
        self.client = self.Param1.ClientEdit.text()
        self.user = self.Param1.tab.gen.UserEdit.text()
        self.password = self.Param1.tab.gen.PassWordEdit.text()
        self.visionValue = self.Param1.tab.gen.visionComboBox.currentText()
        self.cleanssionValue = self.Param1.tab.gen.CleanSessionComboBox.currentText()
        self.napsBooL = self.Param1.tab.gen.groupBox.isChecked()#namepassword 框是否勾选
        self.pascheck = self.Param1.tab.gen.checkBox1.checkState()
        self.file = self.Param1.tab.tls.openFileNameLabel.text()
        print self.file
#         print self.pascheck
#         print self.napsBooL
        if self.cleanssionValue =='True':
            self.cleanssion = True
#             print self.cleanssion
        else:
            self.cleanssion = False
#             print self.cleanssion

        count = len(childlist)
        for x in range(count):
            if rot == x :
                childlist[rot].setText(0,self.tr(self.name))
#         print self.idname
        c = self.conn.cursor()
        c.execute('''UPDATE MQ SET CONNAME = '%s' ,HOSTNAME = '%s', PORT = %d, KEEPLIVE = %d, CLIENTID = '%s', USERNAME = '%s', PASSWORD = '%s', CLEANSSID = '%s', MQVISION = '%s', NAPSBOOL = %d\
        where CONNAME = '%s' ''' %(self.name, self.host, self.portValue, self.keepValue, self.client, self.user, self.password, self.cleanssionValue, self.visionValue, self.napsBooL, self.idname))
        c.execute('''UPDATE MQ1 SET CONNAME = '%s' ,PASCHECK = %d, FILE = '%s'\
        where CONNAME = '%s' ''' %(self.name, self.pascheck, self.file, self.idname))
        self.conn.commit()

        QMessageBox.information(self, self.tr("提示"),
                                        self.tr("保存成功"))

    def add(self):
        self.name = self.Param1.nameEdit.text()
        self.host = self.Param1.HostEdit.text()
        self.portValue = self.Param1.portSpinbox.value()
        self.keepValue = self.Param1.keepaliveSpinbox.value()
        self.client = self.Param1.ClientEdit.text()
        self.user = self.Param1.tab.gen.UserEdit.text()
        self.password = self.Param1.tab.gen.PassWordEdit.text()
        self.visionValue = self.Param1.tab.gen.visionComboBox.currentText()
        self.cleanssionValue = self.Param1.tab.gen.CleanSessionComboBox.currentText()
        self.napsBooL = self.Param1.tab.gen.groupBox.isChecked()
        self.pascheck = self.Param1.tab.gen.checkBox1.checkState()
        self.file = self.Param1.tab.tls.openFileNameLabel.text()
        print self.file
        self.index += 1
        self.child = QtGui.QTreeWidgetItem(self.root)
        randomID = "connect_"+"".join(random.choice("0123456789ADCDEF") for x in range(15-5))
        self.child.setText(0,self.tr(randomID))  
        childlist.append(self.child)
        self.conn.execute("INSERT INTO MQ VALUES ('%s','%s', %d, %d,'%s','%s','%s','%s','%s', %d)"%(randomID, self.host, self.portValue, self.keepValue,\
                                                              self.client, self.user, self.password, self.cleanssionValue, self.visionValue, self.napsBooL))
        self.conn.execute("INSERT INTO MQ1 VALUES ('%s', %d, '%s')"%(randomID, self.pascheck, self.file))

    def delete(self):
        count = len(childlist)
        for x in range(count):
            if rot == x :
                self.root.removeChild(childlist[rot])
                childlist.remove(childlist[rot])
        self.conn.execute("DELETE FROM MQ WHERE CONNAME = '%s' " % (self.idname))
        self.conn.execute("DELETE FROM MQ1 WHERE CONNAME = '%s' " % (self.idname))

    def initDB(self):
        if os.path.exists('MQ.db'):
            self.conn = sqlite3.connect('MQ.db')
            self.conn.isolation_level = None
        else:
            self.conn = sqlite3.connect('MQ.db')
            self.conn.isolation_level = None
            self.conn.execute('''CREATE TABLE MQ
                        (CONNAME char PRIMARY KEY NOT NULL,
                        HOSTNAME char(255),
                        PORT INT,
                        KEEPLIVE INT,
                        CLIENTID char(255),
                        USERNAME char(255),
                        PASSWORD char(255),
                        CLEANSSID BOOLEAN,
                        MQVISION char(255),
                        NAPSBOOL BOOLEAN)''')
            self.conn.execute('''CREATE TABLE MQ1
                        (CONNAME char PRIMARY KEY NOT NULL,
                        PASCHECK INT,
                        FILE char(255))''')
        self.cur = self.conn.cursor()
        self.cur.execute('SELECT * FROM MQ')
        self.MQData = self.cur.fetchall()
        self.cur.execute('SELECT * FROM MQ1')
        self.MQData1 = self.cur.fetchall()
        self.cur.close()
        self.index = len(self.MQData)
        if self.index > 0 :
            for x in range(self.index):
                self.child = QtGui.QTreeWidgetItem(self.root)
#                 print self.child
                childlist.append(self.child)
                id = self.MQData[x][0]
                self.child.setText(0,self.tr(id))

class Param(QtGui.QDialog):
    def __init__(self, parent=None):
        super(Param, self).__init__(parent)
#         self.resize(800,400)
        nameGroup = QtGui.QGroupBox("Name Profile")
        nameLabel = QtGui.QLabel("Connect Name:")
        self.nameEdit = QtGui.QLineEdit()
        '''只允许输入字母和数字'''
        re1=QtCore.QRegExp("[a-zA-Z0-9]+$")
        self.nameEdit.setValidator(QtGui.QRegExpValidator(re1,self))
        ''''''
        ClientGroup = QtGui.QGroupBox("CLient Profile")
        Hostlabel = QtGui.QLabel("HostName:")
        self.HostEdit = QtGui.QLineEdit()
        Portlabel = QtGui.QLabel("Port:")
        ClientIdlabel = QtGui.QLabel("ClientId:")
        self.ClientEdit = QtGui.QLineEdit()
        Keepalivelabel = QtGui.QLabel("Keepalive:")
        checkBox1 = QtGui.QCheckBox("clean_session")
        Button1 = QtGui.QPushButton("Generate")

        amendPushButton = QtGui.QPushButton(self.tr("Apply"))
        closePushButton = QtGui.QPushButton(self.tr("关闭"))
        buttonLayout = QtGui.QHBoxLayout()
        buttonLayout.addStretch(0)
#         buttonLayout.addWidget(amendPushButton)
#         buttonLayout.addWidget(closePushButton)

        self.portSpinbox = QtGui.QSpinBox()
        self.portSpinbox.setMaximum(9999) 
        self.portSpinbox.setMinimum(0)
#         self.portSpinbox.setValue(1883)

        self.keepaliveSpinbox = QtGui.QSpinBox()
        self.keepaliveSpinbox.setMaximum(9999) 
        self.keepaliveSpinbox.setMinimum(0)
#         self.keepaliveSpinbox.setValue(60)

        nameLayout = QtGui.QGridLayout()
        nameLayout.addWidget(nameLabel, 0, 0)
        nameLayout.addWidget(self.nameEdit, 0, 1)
        nameGroup.setLayout(nameLayout)

        inputMaskLabel = QtGui.QLabel("MQTT")
        self.inputMaskComboBox = QtGui.QComboBox()
        self.inputMaskComboBox.addItem("V3.1")
        self.inputMaskComboBox.addItem("V3.1.1")

        inputMaskLabel1 = QtGui.QLabel("Clean_session")
        self.inputMaskComboBox1 = QtGui.QComboBox()
        self.inputMaskComboBox1.addItem("True")
        self.inputMaskComboBox1.addItem("False")


        '''槽函数'''
        Button1.clicked.connect(self.gengrate)
        ''''''

        clientLayout = QtGui.QGridLayout()
        clientLayout.addWidget(Hostlabel, 0, 0)
        clientLayout.addWidget(self.HostEdit, 0, 1)
        clientLayout.addWidget(Portlabel, 0,2)
        clientLayout.addWidget(self.portSpinbox, 0,3)
        clientLayout.addWidget(Keepalivelabel, 1, 0)
        clientLayout.addWidget(self.keepaliveSpinbox, 1, 1, 1, 3)
        clientLayout.addWidget(ClientIdlabel, 2,0)
        clientLayout.addWidget(self.ClientEdit, 2, 1, 1, 2)
        clientLayout.addWidget(Button1,2,3) 
        ClientGroup.setLayout(clientLayout)

        self.tab=TabDialog()
        mainLayout = QtGui.QVBoxLayout()
        mainLayout.addWidget(nameGroup)
        mainLayout.addWidget(ClientGroup)
        mainLayout.addWidget(self.tab)
        mainLayout.addLayout(buttonLayout)
        mainLayout.addSpacing(2)
        mainLayout.addStretch()

        self.setLayout(mainLayout)


    def gengrate(self):
        gen = "Admin_" + "".join(random.choice("0123456789ADCDEF") for x in range(23-5))
        self.ClientEdit.setText(gen)



class TabDialog(QtGui.QWidget):
    def __init__(self,  parent=None):
        super(TabDialog, self).__init__(parent)
        tabWidget = QtGui.QTabWidget()
        self.gen=GeneralTab()
        self.tls=TLSTab()
        tabWidget.addTab(self.gen, "General")
        tabWidget.addTab(self.tls, "TLS")

        mainLayout = QtGui.QVBoxLayout()
        mainLayout.addWidget(tabWidget)
        self.setLayout(mainLayout)    


class GeneralTab(QtGui.QWidget):
    def __init__(self,  parent=None):
        super(GeneralTab, self).__init__(parent)

#         clean_session_checkBox = QtGui.QCheckBox("clean_session")
        groupBox = QtGui.QGroupBox("UserName && PassWord")
        visionLabel = QtGui.QLabel("MQTT vision:")
        self.visionComboBox = QtGui.QComboBox()
        self.visionComboBox.addItem("V3.1")
        self.visionComboBox.addItem("V3.1.1")

        CleanSessionLabel = QtGui.QLabel("Clean session:")
        self.CleanSessionComboBox = QtGui.QComboBox()
        self.CleanSessionComboBox.addItem("True")
        self.CleanSessionComboBox.addItem("False")


        VersionLayout = QtGui.QGridLayout()
        VersionLayout.addWidget(CleanSessionLabel,0,0)
        VersionLayout.addWidget(self.CleanSessionComboBox,0,1)
        VersionLayout.addWidget(visionLabel,1,0)
        VersionLayout.addWidget(self.visionComboBox,1,1)

        grid = QtGui.QGridLayout()
        grid.addWidget(self.createuserGroup(), 0, 0)
        grid.addLayout(VersionLayout, 1, 0)
        grid.setColumnStretch(1,0)
        self.setLayout(grid)

        '''槽函数'''

        ''''''

    def createuserGroup(self):
        self.groupBox = QtGui.QGroupBox("UserName && PassWord")
        self.groupBox.setCheckable(True)
        self.groupBox.setChecked(True)

        UserLabel = QtGui.QLabel("UserName:")
        self.UserEdit = QtGui.QLineEdit()
#         self.UserEdit.setText('liuxh')
        PassWordLabel = QtGui.QLabel("PassWord:")
        self.PassWordEdit = QtGui.QLineEdit()
#         self.PassWordEdit.setText('123456')
        self.checkBox1 = QtGui.QCheckBox("")
#         self.checkBox1.setCheckState(True)      
        '''槽函数'''
        self.checkBox1.stateChanged.connect(self.hide) 
        ''''''
        self.checkBox1.setChecked(True)


        NamePassLayout = QtGui.QGridLayout()
        NamePassLayout.addWidget(UserLabel,0,0)
        NamePassLayout.addWidget(self.UserEdit,0,1)
        NamePassLayout.addWidget(PassWordLabel,1,0)
        NamePassLayout.addWidget(self.PassWordEdit,1,1)
        NamePassLayout.addWidget(self.checkBox1,1,2)

        vbox = QtGui.QVBoxLayout()
        vbox.addLayout(NamePassLayout)
        vbox.addStretch()
        self.groupBox.setLayout(vbox)

        return self.groupBox

    def hide(self):
#         print self.checkBox1.checkState()
        if self.checkBox1.checkState() == 2:
            self.PassWordEdit.setEchoMode(QtGui.QLineEdit.Password)
        else:
            self.PassWordEdit.setEchoMode(QtGui.QLineEdit.Normal)

class TLSTab(QtGui.QDialog):
    def __init__(self,  parent=None):
        super(TLSTab, self).__init__(parent)   
        frameStyle = QtGui.QFrame.Sunken | QtGui.QFrame.Panel
        groupBox = QtGui.QGroupBox("CA certificate")  
        self.openFileNameLabel = QtGui.QLabel()
        self.openFileNameButton = QtGui.QPushButton("open")
        self.openFileNameLabel.setFrameStyle(frameStyle)
        self.openFileNameLabel.setStyleSheet("background:white") 

        TLSLayout = QtGui.QGridLayout()
        TLSLayout.addWidget(self.openFileNameLabel,0,0,1,5)
        TLSLayout.addWidget(self.openFileNameButton,0,6,1,1)
        groupBox.setLayout(TLSLayout)

        SSLLayout1 = QtGui.QGridLayout()
        SSLLayout1.addWidget(groupBox,0,0)
        self.setLayout(SSLLayout1)

        self.openFileNameButton.clicked.connect(self.setOpenFileName1)


    def setOpenFileName1(self):    
        options = QtGui.QFileDialog.Options()
        fileName = QtGui.QFileDialog.getOpenFileName(self,
                "QFileDialog.getOpenFileName()",
                self.openFileNameLabel.text(),
                "All Files (*);;Text Files (*.txt)")
        if fileName:
            self.openFileNameLabel.setText(fileName)     


mtest.py

from PyQt4 import QtCore, QtGui
import sys, socket, binascii
import mqttimage,time
import paho.mqtt.publish as publish
import paho.mqtt.client as mqtt
from ConfigDialog import *
import ctypes 

QtCore.QTextCodec.setCodecForTr(QtCore.QTextCodec.codecForName("utf8"))
ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID("myappid") #状态栏单独显示


class MainWindow(QtGui.QMainWindow):
    def __init__(self,parent=None):
        super(MainWindow,self).__init__(parent)
        self.setWindowTitle(self.tr("MQ TEST"))
        self.setWindowIcon(QtGui.QIcon(":img/image/mq.png"));
        QtCore.QThread.sleep(0)#启动画面停留时间
        QtGui.QApplication.setStyle(QtGui.QStyleFactory.create('Cleanlooks'))#设置整体风格
        QtGui.QApplication.setPalette(QtGui.QApplication.style().standardPalette())#设置整体风格
        self.resize(800,550)#####设置窗口大小
#         self.statusBar().showMessage(self.tr("未建立连接"))
#         self.StackDialog=StackDialog()
        # 开始装载样式表
#         qss_file = open('style.qss').read()
#         self.setStyleSheet(qss_file)
        self.a = MQ()
        self.setCentralWidget(self.a)
        self.createActions()
        self.createMenus()
        self.createToolBars()



    def createActions(self):
#         self.fileOpenAction=QtGui.QAction(QtGui.QIcon(":pic/image/xitong/folder_blue.png"),self.tr("打开"),self)
#         self.fileOpenAction.setShortcut("Ctrl+O")
#         self.fileOpenAction.setStatusTip(self.tr("打开一个文件"))
#         self.connect(self.fileOpenAction,QtCore.SIGNAL("triggered()"),self.slotOpenFile)

        self.fileSaveAction=QtGui.QAction(QtGui.QIcon(":pic/image/xitong/save.png"),self.tr("保存"),self)
        self.fileSaveAction.setShortcut("Ctrl+S")
        self.fileSaveAction.setStatusTip(self.tr("保存文件"))
        self.connect(self.fileSaveAction,QtCore.SIGNAL("triggered()"),self.fileSaveAs)

        self.settingAction=QtGui.QAction(QtGui.QIcon(":img/image/setting.png"),self.tr("设置"),self)
        self.settingAction.setShortcut("Ctrl+H")
        self.settingAction.setStatusTip(self.tr("设置"))
        self.settingAction.triggered.connect(self.a.osd)

        self.aboutAction=QtGui.QAction(QtGui.QIcon(":img/image/mq.png"),self.tr("关于"),self)
        self.aboutAction.setShortcut("Ctrl+j")
        self.aboutAction.triggered.connect(self.about)

        self.actionQuit = QtGui.QAction(self.tr("退出"), self, shortcut=QtGui.QKeySequence.Quit)
        self.actionQuit.triggered.connect(self.close)


    def createMenus(self):
        fileMenu = self.menuBar().addMenu(self.tr("文件"))
#         fileMenu.addAction(self.fileOpenAction)
#         fileMenu.addAction(self.fileSaveAction)
        fileMenu.addAction(self.settingAction)
        fileMenu.addAction(self.actionQuit)
        helpMenu = self.menuBar().addMenu(self.tr("帮助"))
        helpMenu.addAction(self.aboutAction)


    def createToolBars(self):
        fileToolBar=self.addToolBar("File")
#         fileToolBar.addAction(self.fileOpenAction)
#         fileToolBar.addAction(self.fileSaveAction)
        fileToolBar.addAction(self.settingAction)

    def slotOpenFile(self):
        fileName=QtGui.QFileDialog.getOpenFileName(self)
        if fileName.isEmpty()==False:
            if self.text.document().isEmpty():
                self.loadFile(fileName)
            else:
                newWin=MainWindow()
                newWin.show()
                newWin.loadFile(fileName)

    def slotSaveFile(self):
        pass

    def fileSave(self):
        printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
        printer.setOutputFormat(QtGui.QPrinter.PdfFormat)
        browser.document().print_(printer)

    def fileSaveAs(self):   
        printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
        dlg = QtGui.QPrintDialog(printer, self)

#         if self.textEdit.textCursor().hasSelection():
#             dlg.addEnabledOption(QtGui.QAbstractPrintDialog.PrintSelection)

        dlg.setWindowTitle("Print Document")

        if dlg.exec_() == QtGui.QDialog.Accepted:
            browser.print_(printer)

        del dlg

    def about(self):
        QtGui.QMessageBox.about(self, "About", 
                "author:liuxiaohu\n"
                "vision:V1.0.0\n"
                "by Python 2.7 && PyQt4")  

class MQ(QtGui.QWidget):
    def __init__(self, parent=None):
        super(MQ, self).__init__(parent)

        nameLabel = QtGui.QLabel()
        nameLabel.setPixmap(QtGui.QPixmap(":img/image/note.png"))
        frameStyle = QtGui.QFrame.Sunken | QtGui.QFrame.Panel
        self.nameEdit = QtGui.QLineEdit()
        self.nameEdit.setStyleSheet(" height:20px;width: 60px;background:white")
        self.nameEdit.setEnabled(False)
        global dataflag#数据刷新标志

        self.ConnectButton = QtGui.QPushButton(self.tr("连接"))
#         self.ConnectButton.setStyleSheet(" width: 60px;")
        self.ConnectButton.setIcon(QtGui.QIcon(":img/image/tuxiang/connected.png"))
        self.DisConnectButton = QtGui.QPushButton(self.tr("断开"))
        self.DisConnectButton.setDisabled(True)
#         self.DisConnectButton.setStyleSheet(" width: 60px;")
        self.DisConnectButton.setIcon(QtGui.QIcon(":img/image/tuxiang/disconnected.png"))

        self.SettingButton = QtGui.QPushButton()
        self.SettingButton.setIcon(QtGui.QIcon(":img/image/disconnect.png"))
        self.SettingButton.setFlat(True)

        '''槽函数''' 
#         self.SettingButton.clicked.connect(self.osd)
        self.ConnectButton.clicked.connect(self.conne)
        self.DisConnectButton.clicked.connect(self.disconne)

        ''''''
#         self.PubLabel = QtGui.QLabel("Retained")



        self.portSpinbox = QtGui.QSpinBox()
        self.portSpinbox.setMaximum(9999) 
        self.portSpinbox.setMinimum(0)
        self.portSpinbox.setValue(1883)

        self.keepaliveSpinbox = QtGui.QSpinBox()
        self.keepaliveSpinbox.setMaximum(9999) 
        self.keepaliveSpinbox.setMinimum(0)
        self.keepaliveSpinbox.setValue(60)

        nameLayout = QtGui.QGridLayout()
        nameLayout.addWidget(nameLabel, 0, 0,)
        nameLayout.addWidget(self.nameEdit, 0, 1)
        nameLayout.addWidget(self.SettingButton,0, 2)
        nameLayout.addWidget(self.ConnectButton, 0, 3)
        nameLayout.addWidget(self.DisConnectButton, 0, 4)  

        self.tab=TabDialog()
        mainLayout = QtGui.QVBoxLayout()
        mainLayout.addLayout(nameLayout)
        mainLayout.addWidget(self.tab)
        mainLayout.addSpacing(6)
#         mainLayout.setMargin(0)
#         mainLayout.addStretch()

        self.setLayout(mainLayout)

    def osd(self):  
        global ProfileName, Host, portValue, keepValue, clientids, user, password, visionValue, cleanssionValue, napsBooL, pascheck 
        dialog=ConfigDialog(self)
        result = dialog.exec_()
        for x in range(len(childlist)):
            childlist.remove(childlist[0])
        if result:
            ProfileName, Host, portValue, keepValue, clientids, user, password, visionValue,  cleanssionValue, napsBooL, pascheck = dialog.getsetdata()
            print ProfileName, Host, portValue, keepValue, clientids, user, password, visionValue,  cleanssionValue, napsBooL, pascheck   
            self.nameEdit.setText(ProfileName)
        dialog.destroy()


    def on_connect(self, client, obj, flags, rc):
        print("rc: "+str(rc))
        if str(rc) == '0':
            self.bwThread.updatedicon.emit()#发送信号


    def icon(self):     
        self.SettingButton.setIcon(QtGui.QIcon(":img/image/connect.png"))  
        self.ConnectButton.setDisabled(True) 
        pub.setDisabled(False)
        sub.setDisabled(False)

    def disconne(self): 
        pub.setDisabled(True)
        sub.setDisabled(True)  
        client.disconnect()
        self.bwThread.stop()
        self.SettingButton.setIcon(QtGui.QIcon(":img/image/disconnect.png"))  
        self.ConnectButton.setDisabled(False)
#         self.stopTimer()

    def initTimer(self):    
        self.timer = QtCore.QTimer(self) #初始化一个定时器
        self.timer.timeout.connect(self.pingreq) #计时结束调用operate()方法
        self.timer.start((keepValue-1)*1000) #设置计时间隔并启动

    def stopTimer(self):    
        self.timer.stop() 

    def conne(self):
        try:
            if visionValue == QtCore.QString('V3.1.1'):
                self.mqttvision = mqtt.MQTTv311
            else:
                self.mqttvision = mqtt.MQTTv31

            hostname = unicode(QtCore.QString(Host).toUtf8(),'utf8','ignore')
            clientid = unicode(QtCore.QString(clientids).toUtf8(),'utf8','ignore')
            self.username = unicode(QtCore.QString(user).toUtf8(),'utf8','ignore')
            self.pswd = unicode(QtCore.QString(password).toUtf8(),'utf8','ignore')
#             print type(hostname)
            self.DisConnectButton.setDisabled(False)

            global client
            client = mqtt.Client(client_id=clientid, clean_session=cleanssionValue, userdata=None, protocol=self.mqttvision)
            client.on_publish = self.on_publish
            client.on_connect = self.on_connect 
            client.on_message = self.on_message
            client.on_subscribe = self.on_subscribe

            if napsBooL == True:
                self.setAutho() #设置用户名和密码
            try:

                client.connect(hostname, keepalive = keepValue) #向服务器发起连接
#                 self.initTimer()
                self.bwThread = WorkThread()
                self.bwThread.updated.connect(self.append)
                self.bwThread.updatedicon.connect(self.icon)
                rc = self.bwThread.start()
                return rc
            except socket.error:
                QMessageBox.information(self, self.tr("提示"), self.tr("服务器地址不存在,请重新输入"))
            except ValueError:
                QMessageBox.critical(self, self.tr("提示"), self.tr("请输入正确服务器地址"))
        except NameError:
            QMessageBox.information(self, self.tr("提示"), self.tr("请在设置页面选择相应的配置文件"))

    def pingreq(self):
        client.send_pingreq()

    def on_message(self, mqttc, obj, msg):
        global a,b,c
        a = msg.topic
        b = msg.qos
        c = msg.payload
        self.bwThread.updated.emit()#发送信号
#         print(msg.topic+" "+str(msg.qos)+" "+str(msg.payload))


    def strformathex(self, str):
        self.index=0
        self.a=list()
        self.b=list(str)
        self.len = len(str)/2
        for i in range(self.len):
            self.a.append(self.b[self.index]+self.b[self.index+1])
            self.a.append(" ")
            self.index=self.index+2
        return ''.join(self.a)

    def append(self):
        browser.append(a+" "+str(b)+" "+str(c))    
        m = binascii.b2a_hex(c)
        h = self.strformathex(m)
        h.rstrip()
        t = time.asctime( time.localtime(time.time()) )
        browser.append(a+" "+str(b)+" "+ h + " "+t)  



    def on_publish(self, mqttc, obj, mid):
        print("message mid is: "+str(mid))

    def on_subscribe(self, mqttc, obj, mid, granted_qos):
        print("Subscribed: "+str(mid)+" "+str(granted_qos))

    def on_log(self, mqttc, obj, level, string):
        print(string)

    def setAutho(self):
        client.username_pw_set(self.username, self.pswd)   


class WorkThread(QtCore.QThread):
    updated  = QtCore.pyqtSignal()#自定义信号,更新数据
    updatedicon  = QtCore.pyqtSignal()#自定义信号,更新图标
    def __init__(self, parent=None):
        super(WorkThread, self).__init__(parent)
        self.flag = 1

    def run(self):
        while True:
            if self.flag == 1:
                client.loop()
            else:
                break

    def stop(self):  
        print 'setting flag false'  
        self.flag = 0  
        print self.flag  


class TabDialog(QtGui.QWidget):
    def __init__(self,  parent=None):
        super(TabDialog, self).__init__(parent)
#         self.setGeometry(300,30,30,30)
#         self.show()
        tabWidget = QtGui.QTabWidget()
        style = "QTabWidget::pane{border:none;\
                 QTabWidget::tab-bar{alignment:left;}}\
                 QTabBar::tab{background:#FFF5EE;color:black;min-width:30ex;min-height:10ex;}\
                 QTabBar::tab:hover{background:rgb(255, 255, 255, 255);}\
                 QTabBar::tab:selected{border-color:white;background:#00BFFF;color:white;}"
        tabWidget.setStyleSheet(style)    
        global pub, sub              
        pub=PublishTab()
        sub=SubTab()
        pub.setDisabled(True)
        sub.setDisabled(True)
        tabWidget.addTab(pub, "Publish")
        tabWidget.addTab(sub, "Subcribe")

        mainLayout = QtGui.QGridLayout()
        mainLayout.addWidget(tabWidget,5,1)
        mainLayout.setMargin(1)
        mainLayout.setSpacing(6) 
        self.setLayout(mainLayout) 

class PublishTab(QtGui.QWidget):    
    def __init__(self,  parent=None):
        super(PublishTab, self).__init__(parent)     
        publishGroup = QtGui.QGroupBox("Publish Message")
        self.PubLabel = QtGui.QLabel("PubTopic:")
        self.Playload = QtGui.QLabel("Message :")
        self.pubEdit = QtGui.QLineEdit()
        self.PlayloadEdit = QtGui.QLineEdit()
        self.PlayloadEdit.setStyleSheet(" height: 37px;")
        self.PushButton = QtGui.QPushButton(self.tr("Publish"))
        self.PushButton.setStyleSheet(" height: 50px;background:#D3D3D3")
        global pubbrowser
        pubbrowser = QtGui.QTextBrowser()
        pubbrowser.setFrameStyle(QtGui.QFrame.Panel|QtGui.QFrame.Sunken)
#         style = "color: rgb(127, 0, 63);\
#                 background-image: url(:img/image/3.jpg);"
        style = "color:#7CFC00;background:#4D4D4D"
        pubbrowser.setStyleSheet(style)

        self.QosLabel = QtGui.QLabel("Qos")
        self.QosComboBox = QtGui.QComboBox()
        self.QosComboBox.addItem("0")
        self.QosComboBox.addItem("1")
        self.QosComboBox.addItem("2") 

        self.formatLabel = QtGui.QLabel("Send Format")
        self.formatComboBox = QtGui.QComboBox()
        self.formatComboBox.addItem("HEX")
        self.formatComboBox.addItem("Plain")

        self.Retained = QtGui.QCheckBox("Retained")

        self.pubLayout = QtGui.QGridLayout()
        self.pubLayout.addWidget(self.PubLabel,0,0)
        self.pubLayout.addWidget(self.pubEdit,0,1)
        self.pubLayout.addWidget(self.QosLabel,0,2)
        self.pubLayout.addWidget(self.QosComboBox,0,3)
        self.pubLayout.addWidget(self.Retained,0,4)
        self.pubLayout.addWidget(self.Playload,1,0)
        self.pubLayout.addWidget(self.PlayloadEdit,1,1)   
        self.pubLayout.addWidget(self.formatLabel,1,2)
        self.pubLayout.addWidget(self.formatComboBox,1,3,1,2)
        self.pubLayout.setSpacing(10)

        self.Vlineframe = QtGui.QFrame()
        self.Vlineframe.setFrameStyle(QtGui.QFrame.VLine|QtGui.QFrame.Sunken)

        saveButton = QtGui.QPushButton(self.tr("保存"))
        saveButton.setFlat(True)
        saveButton.setIcon(QtGui.QIcon(":img/image/pdf.png"))   
        delButton = QtGui.QPushButton(self.tr("清空"))
        delButton.setFlat(True)          
        delButton.setIcon(QtGui.QIcon(":img/image/recycle.png")) 
        self.buttonLayout1 = QtGui.QGridLayout()
        self.buttonLayout1.addWidget(saveButton,0,0)
        self.buttonLayout1.addWidget(delButton,0,2) 

        '''槽函数''' 
        self.PushButton.clicked.connect(self.push)
        saveButton.clicked.connect(self.save)
        delButton.clicked.connect(self.clear)
        ''''''

        clientLayout = QtGui.QGridLayout()
        clientLayout.addLayout(self.pubLayout, 0, 0)
        clientLayout.addWidget(self.Vlineframe, 0, 1)
        clientLayout.addWidget(self.PushButton, 0, 2)
        publishGroup.setLayout(clientLayout)

        mainLayout = QtGui.QVBoxLayout()
        mainLayout.addWidget(publishGroup)
        mainLayout.addWidget(pubbrowser)
        mainLayout.addLayout(self.buttonLayout1)
        mainLayout.addSpacing(2)
        self.setLayout(mainLayout)



    def push(self):  
        x = time.asctime( time.localtime(time.time()) )
        self.pubtopic = self.pubEdit.text()
        self.pubtopic = unicode(QtCore.QString(self.pubtopic).toUtf8(),'utf8','ignore')
        self.pubmessage = self.PlayloadEdit.text() 
        self.pubmessage = unicode(self.pubmessage)
        pubbrowser.append('[Pubtopic]:---' + self.pubtopic + '---[' + x + ']')
        pubbrowser.append('[Message]:---' + self.pubmessage + '---[' + x + ']')  
        if self.formatComboBox.currentIndex()  == 0:  
#             self.pubmessage = unicode(self.pubmessage)
            self.pubmessage = bytearray().fromhex(self.pubmessage)

        if self.QosComboBox.currentText()  == QtCore.QString('0'):
            self.qos = 0 
        elif self.QosComboBox.currentText()  == QtCore.QString('1'):
            self.qos = 1 
        if self.QosComboBox.currentText()  == QtCore.QString('2'):
            self.qos = 2 
        self.Retain = self.Retained.checkState() 
#         print self.pubtopic, self.pubmessage, self.qos, self.Retain
        client.publish(self.pubtopic, self.pubmessage)

    def save(self):
        printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
        dlg = QtGui.QPrintDialog(printer, self)
        dlg.setWindowTitle("Print Document")
        if dlg.exec_() == QtGui.QDialog.Accepted:
            pubbrowser.print_(printer)
        del dlg

    def clear(self):  
        pubbrowser.clear()   


class SubTab(QtGui.QWidget):    
    def __init__(self,  parent=None):
        super(SubTab, self).__init__(parent)  
        SublishGroup = QtGui.QGroupBox("Subscribe")
        self.SubLabel = QtGui.QLabel("SubTopic:")
        self.SubEdit = QtGui.QLineEdit()
        self.SubEdit.setText('$SYS/broker/bytes/received')
        self.SubButton = QtGui.QPushButton(self.tr("Subscribe"))
        self.SubButton.setStyleSheet(" height: 50px;background:#D3D3D3")
        global browser
        browser = QtGui.QTextBrowser()
        browser.setFrameStyle(QtGui.QFrame.Panel|QtGui.QFrame.Sunken)
        browser.ensureCursorVisible()#滚动条自动
#         style = "color: rgb(127, 0, 63);\
#                 background-image: url(:img/image/3.jpg);"
        style = "color:#ffffff;background:#000000"
        browser.setStyleSheet(style)

        self.QosLabel = QtGui.QLabel("Qos")
        self.QosComboBox = QtGui.QComboBox()
        self.QosComboBox.addItem("0")
        self.QosComboBox.addItem("1")
        self.QosComboBox.addItem("2") 


        self.pubLayout = QtGui.QGridLayout()
        self.pubLayout.addWidget(self.SubLabel,0,0)
        self.pubLayout.addWidget(self.SubEdit,0,1)
        self.pubLayout.addWidget(self.QosLabel,0,2)
        self.pubLayout.addWidget(self.QosComboBox,0,3) 
        self.pubLayout.setSpacing(10)

        self.Vlineframe = QtGui.QFrame()
        self.Vlineframe.setFrameStyle(QtGui.QFrame.VLine|QtGui.QFrame.Sunken)

        saveButton = QtGui.QPushButton(self.tr("保存"))
        saveButton.setFlat(True)
        saveButton.setIcon(QtGui.QIcon(":img/image/pdf.png"))   
        delButton = QtGui.QPushButton(self.tr("清空"))
        delButton.setFlat(True)          
        delButton.setIcon(QtGui.QIcon(":img/image/recycle.png")) 
        self.buttonLayout1 = QtGui.QGridLayout()
        self.buttonLayout1.addWidget(saveButton,0,0)
        self.buttonLayout1.addWidget(delButton,0,2) 

        '''槽函数''' 
        self.SubButton.clicked.connect(self.sub)
        saveButton.clicked.connect(self.save)
        delButton.clicked.connect(self.clear)
        ''''''

        clientLayout = QtGui.QGridLayout()
        clientLayout.addLayout(self.pubLayout, 0, 0)
        clientLayout.addWidget(self.Vlineframe, 0, 1)
        clientLayout.addWidget(self.SubButton, 0, 2)
#         clientLayout.addWidget(self.browser, 1, 0, 1, 3)
#         self.pubLayout.setSpacing(2)
        SublishGroup.setLayout(clientLayout)


        mainLayout = QtGui.QVBoxLayout()
        mainLayout.addWidget(SublishGroup)
        mainLayout.addWidget(browser)
        mainLayout.addLayout(self.buttonLayout1)
        mainLayout.addSpacing(2)
        self.setLayout(mainLayout)

    def sub(self):  
        x = time.asctime( time.localtime(time.time()) )
        self.subtopic = self.SubEdit.text()
        self.subtopic = str(self.subtopic)#类型转换很重要
        browser.append('[Subtopic]:---' + self.subtopic +'---[' + x + ']')    
        if self.QosComboBox.currentText()  == QtCore.QString('0'):
            self.qos = 0 
        elif self.QosComboBox.currentText()  == QtCore.QString('1'):
            self.qos = 1 
        if self.QosComboBox.currentText()  == QtCore.QString('2'):
            self.qos = 2 
        client.subscribe(self.subtopic,self.qos)

    def save(self):
        printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution)
        dlg = QtGui.QPrintDialog(printer, self)
        dlg.setWindowTitle("Print Document")
        if dlg.exec_() == QtGui.QDialog.Accepted:
            browser.print_(printer)
        del dlg

    def clear(self):  
        browser.clear()   


if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    splash = QtGui.QSplashScreen(QtGui.QPixmap(":img/image/mqtt.GIF"))
    splash.show()
    app.processEvents()
    mainWin = MainWindow()
    mainWin.show()
    splash.finish(mainWin)
    sys.exit(app.exec_())   

附上地址:github

目前只是一个手工测试工具,还不能实现自动测试,对PYQT感兴趣的同学可以互相探讨一下

你可能感兴趣的:(测试工具,python,测试工具,MQTT)