解决Python Socket UDP端口侦听线程内更新UI界面卡顿、奔溃的问题

 网络读卡器介绍:WIFI无线网络RFID云读卡器远程网络开关物流网NB-IoT4G刷卡阅读器-淘宝网 (taobao.com)

   Python使用PyQt5做UI界面,开启线程侦听UDP端口,端口接收到网络读卡器的读卡数据后刷新UI界面显示接收数据,解析数据包信息并向读卡器发送显示文字、驱动读卡器播报语音、蜂鸣响声提示、开启继电器开关等操作。

    在接收数据的子线程内如果直接更改UI窗口控件来显示信息,会产生显示信息刷新不及时、造成显示卡顿、卡死或软件直接奔溃等问题,产生原因是PyQt5中,数据接收处理子线程内是不能刷新UI显示线程的,必段使用创建信号,触发时将显示信号传送给槽函数来刷新UI的方式。

import socket
import time
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QDateTime

class SockListenThread(QThread):      #Socket端口侦听线程
    Sock_data = pyqtSignal(int,str)   # 创建一个信号,触发时传递显示信息给槽函数

    def run(self):
        while listen==1:
            try:
                data, addr = s.recvfrom(1024)  #UDP端口接收到数据
                RemortIPort = '%s:%s' % addr
                self.Sock_data.emit(1,RemortIPort)

                GetData = 'FromIP:%s:%s' % addr + '    Data:'
                for num in range(0, len(data)):
                    GetData = GetData + '%02X ' % (data[num])
                self.Sock_data.emit(2,GetData)
            except:
                self.Sock_data.emit(2, 'The socket is being reopened')


在UI界面初始化内绑定槽函数:
    self.subSockListenThread=SockListenThread() 
    self.subSockListenThread.Sock_data.connect(self.SockGetData) 
    self.subSockListenThread.start()

槽函数更新UI
    def SockGetData(self,dispcode,Getdata):
        if(dispcode==1):
            self.textEdit_7.setText(Getdata)
        elif(dispcode==2):
            self.listWidget.addItem(Getdata)
            self.ListBottom() 

       其实这不仅仅Python、Pyqt5开发UI界面时要这样处理,Visual Studio C#、vb.net等多线程开发工具,在子线程更新UI窗口显示信息时,都要用类似的方式,虽然有个 CheckForIllegalCrossThreadCalls = false 设置来强制刷新UI,但是微软并不推荐这样使用(测试发现有时会出现刷新不了的情况)。

C#线程内更新UI界面使用委拖的方式:

delegate void Update1(string text1,string text2);   //线程内更新UI委拖

public  void ThrListener()
{
    while (ready)
     {
        try
        {
            EndPoint RemotePoint = new IPEndPoint(System.Net.IPAddress.Any, 0);
            byte[] bytes = new byte[1024];
            int NumGet = ListenerSock.ReceiveFrom(bytes, ref RemotePoint);

            string Msg = Encoding.GetEncoding(936).GetString(bytes, 0, NumGet);

            string dispstr = DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss") + "Data:";
            RemoteIPoint =(IPEndPoint)RemotePoint;           //获取数据包来源IP及端口,原路回应
            this.BeginInvoke(new Update1(EditUi), dispstr, Msg);  //显示接收到的数据包,并根据情况回应设备
        }
        catch(Exception ex )
        {
            this.BeginInvoke(new Update1(EditUi), DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")+" ",ex.Message  );
        }
    }
 }

private void EditUi(string text1, string Msg)     //刷新显示
 {
    if (ListBox1.Items.Count > 50) { ListBox1.Items.Clear();}
    ListBox1.Items.Add(text1 + Msg);
    ListBox1.SelectedIndex = ListBox1.Items.Count - 1;
}


VB.Net线程内更新UI界面使用委拖的方式:

Delegate Sub EditUi(ByVal data0 As String, ByVal data1 As String)  '线程内更新UI传送两个参数

Private Sub ThrListener() '侦听线程      
    While ready
        Try
            Dim bytes(1024) As Byte
            Dim dataArray() As String
            Dim RemotePoint As System.Net.EndPoint = New System.Net.IPEndPoint(System.Net.IPAddress.Any, 0)
            Dim NumGet As Integer
            Dim Msg As String

            NumGet = ListenerSock.ReceiveFrom(bytes, RemotePoint)
            Msg = Encoding.GetEncoding(936).GetString(bytes, 0, NumGet)

            Me.Invoke(New EditUi(AddressOf EditUiNow), Now() & (" FromIP:" & Convert.ToString(RemotePoint) + "          ").Substring(0, 30) & "Data:", Msg) '用Invoke跨线程更新UI      

            Me.Invoke(New EditTC(AddressOf EditTCNow), 3, Convert.ToString(RemotePoint)) '用Invoke跨线程更新UI

        Catch ex As Exception
            Me.Invoke(New EditTC(AddressOf EditTCNow), 2, "ERROR:" & vbCrLf & ex.GetHashCode & ex.Message & vbCrLf)
        End Try
    End While
End Sub


Private Sub EditTCNow(ByVal con As Integer, ByVal dispinf As String) '这里要和委托定义时的参数保持一致
        Select Case con
            Case 1
                TextBox3.Text = dispinf
            Case 2
                ListBox1.Items.Add(dispinf)
                ListBox1.SelectedIndex = ListBox1.Items.Count - 1
            Case 3
                TextBox1.Text = dispinf
        End Select
End Sub


    真怀念VB6单线程编程,直接刷新窗口显示的时代!  Text1.text="hello world"

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'SockUdpReaderUI.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.

import socket
import time
import threading
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QDateTime
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget,QMessageBox

Bindip=""
Bindprot=0
listen=0
EditUiEn=0
changip=0
LastBuf=bytes(9)                     #保存最后接收到的信息,用于比较是否重复接收的信息
dispinf="端口侦听、UI显示线程已启动!"
RemortIPort=""

CardNuff=bytearray()                #保存C3主动读取IC卡扇区数据

class MyDialog(QThread):            #对话框线程
    sig = pyqtSignal(object)
    def run(self):
        self.sig.emit('')

class EditUIThread(QThread):         #UI界面刷新线程
    update_data = pyqtSignal(str)    # 创建一个信号,触发时将显示信息给槽函数

    def run(self):
        self.update_data.emit(dispinf)


class SockListenThread(QThread):      #Socket端口侦听线程
    Sock_data = pyqtSignal(int,str)   # 创建一个信号,触发时传递显示信息给槽函数

    def run(self):
        global LastBuf
        global CardNuff

        while listen==1:
            try:
                data, addr = s.recvfrom(1024)
                RemortIPort = '%s:%s' % addr
                self.Sock_data.emit(1,RemortIPort)

                GetData = 'FromIP:%s:%s' % addr + '    Data:'
                for num in range(0, len(data)):
                    GetData = GetData + '%02X ' % (data[num])
                self.Sock_data.emit(2,GetData)

                if (len(data) > 8):
                    if (data[0] == LastBuf[0] and data[1] == LastBuf[1] and data[2] == LastBuf[2] and data[3] ==
                            LastBuf[3] and data[4] == LastBuf[4] and data[5] == LastBuf[5] and data[6] == LastBuf[6] and
                            data[7] == LastBuf[7] and data[8] == LastBuf[8]):  # 比较是否是重发数据
                        DisableSendAge(data, addr)      # 接收到重复上传的信息,不用解析处理
                    else:
                        LastBuf = data[0:9]             # 将接收到的信息保存,用于下次接收数据时比对

                        if (data[0] == eval('0xF2')):   # 接收到设备开机、搜索在线设备的返回信息,对信息解析
                            DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])
                            DevMask = '%d.%d.%d.%d' % (data[5], data[6], data[7], data[8])
                            DevPort = '%d' % (data[9] + data[10] * 256)
                            DevNo = '%05d' % (data[11] + data[12] * 256)
                            DevGetway = '%d.%d.%d.%d' % (data[13], data[14], data[15], data[16])
                            GetwayMac = ''
                            for num in range(17, 23):
                                GetwayMac = GetwayMac + '%02X' % (data[num])
                                if (num < 22):
                                    GetwayMac = GetwayMac + '-'
                            ServeIp = '%d.%d.%d.%d' % (data[23], data[24], data[25], data[26])
                            ServerMac = ''
                            for num in range(27, 33):
                                ServerMac = ServerMac + '%02X' % (data[num])
                                if (num < 32):
                                    ServerMac = ServerMac + '-'
                            Search = ('000000'+bin(data[34])[2:])[-6:]+('00'+bin(data[33])[2:])[-2:]    #  '%02X' % (data[33])
                            Beep = str(int(Search,base=2))                             #  '%02X' % (data[34])
                            DevMac = '16-88-'
                            for num in range(35, 39):
                                DevMac = DevMac + '%02X' % (data[num])
                                if (num < 38):
                                    DevMac = DevMac + '-'
                            SerialNum = ''
                            HCMac = ''
                            if (len(data) > 39):
                                for num in range(39, len(data)):
                                    SerialNum = SerialNum + '%02X' % (data[num])

                                    if (num < 45):
                                        HCMac = '%02X' % (data[num]) + HCMac
                                        if (num < 44):
                                            HCMac = '-' + HCMac

                            dispinf = DevNo + "," +DEvIp + "," + DevMask + "," + DevPort + "," +  DevGetway + "," + GetwayMac + "," + ServeIp + "," + ServerMac + "," + Search + "," + Beep+ "," + DevMac[6:17] + "," + DevMac + "," + SerialNum+ "," +HCMac
                            self.Sock_data.emit(3,dispinf)
                            self.Sock_data.emit(4, DevNo)
                            self.Sock_data.emit(2, '数据解析:设备响应搜索指令、开机标识:F2,设备信息已在表格内显示,如需修改设备网络参数,先在表格内更改参数后再点击 "修改选定设备的网络参数" 键!')
                            self.Sock_data.emit(2, '参数标识说明  bit7:卡在隔10秒重发,bit6:卡在隔2秒重发,bit5:卡在隔1秒重发,bit4:卡离开发信息,bit3:DHCP,bit2:刷卡响声,bit1:网关MAC自动获取,bit0:远程服务器MAC自动获取')

                        elif (data[0] == eval('0xF3')):  # 接收到设备的心跳数据包,设备心跳间隔可根据协议自行设置
                            DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])

                        elif (data[0] == eval('0xC1') or data[0] == eval('0xD1')):  # 接收到读取IC、ID卡信息的数据包,对信息解析
                            DisableSendAge(data, addr)
                            FunCode = '%02X' % (data[0])
                            DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])    # 设备IP
                            DevNo = '%05d' % (data[5] + data[6] * 256)                      # 机号
                            FrameNo = '%d' % (data[7] + data[8] * 256)                     # 数据包序号
                            SerialNum = ''                                                  # 设备硬件序列号
                            for num in range(14, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])

                            if(data[0] == eval('0xC1')):
                                Card16H = '%02X%02X%02X%02X' % (data[10], data[11], data[12], data[13])  # 原始16进制卡号
                                Cardno = data[10]
                                Cardno = Cardno + (data[11] * 256)
                                Cardno = Cardno + (data[12] * 65536)
                                Cardno = Cardno + (data[13] * 16777216)
                                CardnoStr = '%010d' % Cardno  # 转10进制卡号
                                dispinf = '数据解析:读IC卡号标识:'
                            else:
                                Card16H = '%02X%02X%02X%02X' % (data[9], data[10], data[11], data[12])  # 原始16进制卡号
                                Cardno = data[9]
                                Cardno = Cardno + (data[10] * 256)
                                Cardno = Cardno + (data[11] * 65536)
                                Cardno = Cardno + (data[12] * 16777216)
                                CardnoStr = '%010d' % Cardno  # 转10进制卡号
                                dispinf = '数据解析:读ID卡号标识:'

                            dispinf = dispinf + FunCode + ',设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H + " 转10进制卡号:" + CardnoStr + ",硬件序列号:" + SerialNum
                            self.Sock_data.emit(4, DevNo)
                            self.Sock_data.emit(2, dispinf)  # UI显示

                            DispStr = '卡号:' + CardnoStr + '  ' + get_time() + '                              '  # 满屏显示,补足后面空格
                            SendDispBeep(DispStr,addr,int(DevNo))         # 向读卡器发送显示及蜂鸣响声

                        elif (data[0] == eval('0xC3')):  # 全扇区读写器收到读卡扇区内的数据(刷卡时主动读取并上传)
                            j = data[10] * 48
                            m = data[11] * 48

                            for num in range(0, m):  # 将读取到的扇区信息存入读卡缓冲
                                CardNuff.append(data[16 + num])

                            if (data[11] + data[10] >= data[9]):  # 已完全收到所有包数据,一个数据包最多传4个扇区的数据,如果读写器设备读写扇区数大于4,数据要分2个包上传,扇区数大于8要分3个包,大与12要分4个包上传
                                FunCode='%02X' % (data[0])
                                DEvIp='%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])
                                DevNo = '%05d' % (data[5] + data[6] * 256)  # 机号
                                FrameNo = '%d' % (data[7] + data[8] * 256)  # 数据包序号
                                Card16H = '%02X%02X%02X%02X' % (data[12], data[13], data[14], data[15])  # 原始16进制卡号
                                dispinf= '数据解析:读IC卡扇区标识:'+ FunCode + ',设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H+ ",读卡信息已在扇区数据栏显示!"
                                self.Sock_data.emit(2, dispinf)  # UI显示

                                m = data[9] * 48
                                CardInfStr = ''
                                for num in range(0, m):
                                    CardInfStr = CardInfStr + '%02X ' % (CardNuff[num])
                                self.Sock_data.emit(5, CardInfStr)  # UI显示

                                CardNuff = bytearray()  # 已接收完,清空接收缓冲

                        elif (data[0] == eval('0xC5')):  # 指定区号、密码读卡返回信息
                            FunCode = '%02X' % (data[0])
                            DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])    # 设备IP
                            DevNo = '%05d' % (data[5] + data[6] * 256)                      # 机号
                            SectNum = data[7]   #扇区总数
                            Card16H = '%02X%02X%02X%02X' % (data[8], data[9], data[10], data[11])
                            Sectors=data[12]       #扇区号
                            dispinf = '数据解析:读IC卡扇区标识:' + FunCode + ',设备IP:' + DEvIp + ',机号:' + DevNo + ",16进制卡号:" + Card16H
                            if (data[13] == 0):
                                CardInfStr = ''
                                for num in range(0, 48):
                                    CardInfStr = CardInfStr + '%02X ' % (data[14 + num])
                                dispinf = dispinf +",读取 "+str(Sectors)+" 扇区数据成功!"
                                self.Sock_data.emit(2, dispinf)         # UI显示
                                self.Sock_data.emit(5, CardInfStr)
                            else:
                                if (data[13] == 12):
                                    dispinf =  dispinf+",卡密码认证失败!本次读卡失败!"
                                    self.Sock_data.emit(2, dispinf)  # UI显示
                                else:
                                    dispinf = dispinf+",读卡失败,错误代码:%02X" % (data[13])
                                    self.Sock_data.emit(2, dispinf)  # UI显示

                        elif (data[0] == eval('0xCD')):  # 响应写卡、更改卡密码后的返回信息
                            FunCode = '%02X' % (data[0])
                            DEvIp = '%d.%d.%d.%d' % (data[2], data[3], data[4], data[5])  # 设备IP
                            DevNo = '%05d' % (data[6] + data[7] * 256)  # 机号
                            SectNum = data[8]       #扇区总数
                            Card16H = '%02X%02X%02X%02X' % (data[9], data[10], data[11], data[12])  # 原始16进制卡号
                            Sectors = data[13]   #扇区号
                            dispinf = '数据解析:写IC卡扇区标识:'  + FunCode + ',设备IP:' + DEvIp + ',机号:' + DevNo + ",16进制卡号:" + Card16H
                            if (data[1] == 0x3A):
                                if (data[14] == 0x00):
                                    dispinf = dispinf +',更改卡密码成功!'
                                elif (data[14] == 0x0C):
                                    dispinf = dispinf +',卡密码认证失败,更改卡密码失败!'
                                else:
                                    dispinf = dispinf +',更改卡密码失败,错误代码:%02X' % (data[14])
                            else:
                                if (data[1] == 0x3D):
                                    if (data[14] == 0x00):
                                        dispinf = dispinf +',写卡成功!'
                                    elif (data[14] == 0x0C):
                                        dispinf = dispinf + ',卡密码认证失败,写卡失败!'
                                    else:
                                        dispinf = dispinf +',写卡失败,错误代码:%02X' % (data[14])
                            self.Sock_data.emit(2, dispinf)  # UI显示

                        elif (data[0] == eval('0xCF') or data[0] == eval('0xDF')):  # 接收到IC、ID卡离开读卡器感应区的信息
                            DisableSendAge(data, addr)
                            FunCode = '%02X' % (data[0])
                            DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])                # 设备IP
                            DevNo = '%05d' % (data[5] + data[6] * 256)                                  # 机号
                            FrameNo = ':%d' % (data[7] + data[8] * 256)                                 # 数据包序号
                            Card16H = '%02X%02X%02X%02X' % (data[11], data[12], data[13], data[14])     # 原始16进制卡号
                            Cardno = data[11]
                            Cardno = Cardno + (data[12] * 256)
                            Cardno = Cardno + (data[13] * 65536)
                            Cardno = Cardno + (data[14] * 16777216)
                            CardnoStr = '%010d' % Cardno    # 转10进制卡号
                            SerialNum = ''                  # 设备硬件序列号
                            for num in range(15, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            if(data[0] == eval('0xCF')):
                                dispinf = '数据解析:IC卡离开标识:'
                            else:
                                dispinf = '数据解析:ID卡离开标识:'
                            dispinf = dispinf + FunCode + ',设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H + " 转10进制卡号:" + CardnoStr + ",硬件序列号:" + SerialNum
                            self.Sock_data.emit(2, dispinf)  # UI显示
                            self.Sock_data.emit(4, DevNo)

            except:
                self.Sock_data.emit(2, 'Socket端口侦听线程正在重启...')


class Ui_Frame(object):
    def setupUi(self, Frame):
        Frame.setObjectName("Frame")
        Frame.resize(1082, 590)
        self.PBSearch = QtWidgets.QPushButton(Frame)
        self.PBSearch.setGeometry(QtCore.QRect(10, 10, 140, 31))
        self.PBSearch.setObjectName("PBSearch")
        self.CBIP = QtWidgets.QComboBox(Frame)
        self.CBIP.setGeometry(QtCore.QRect(156, 10, 180, 31))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.CBIP.setFont(font)
        self.CBIP.setObjectName("CBIP")
        self.tableWidget = QtWidgets.QTableWidget(Frame)
        self.tableWidget.setGeometry(QtCore.QRect(10, 50, 1061, 111))
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(14)
        self.tableWidget.setRowCount(0)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(2, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(3, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(4, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(5, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(6, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(7, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(8, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(9, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(10, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(11, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(12, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(13, item)
        self.PBEditpara = QtWidgets.QPushButton(Frame)
        self.PBEditpara.setGeometry(QtCore.QRect(890, 10, 181, 31))
        self.PBEditpara.setObjectName("PBEditpara")
        self.PBSendDispBeep = QtWidgets.QPushButton(Frame)
        self.PBSendDispBeep.setGeometry(QtCore.QRect(10, 206, 240, 31))
        self.PBSendDispBeep.setObjectName("PBSendDispBeep")
        self.PBSendDispTTS = QtWidgets.QPushButton(Frame)
        self.PBSendDispTTS.setGeometry(QtCore.QRect(10, 296, 240, 31))
        self.PBSendDispTTS.setObjectName("PBSendDispTTS")
        self.CBbeep = QtWidgets.QComboBox(Frame)
        self.CBbeep.setGeometry(QtCore.QRect(320, 206, 111, 31))
        self.CBbeep.setObjectName("CBbeep")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.CBbeep.addItem("")
        self.textEdit = QtWidgets.QTextEdit(Frame)
        self.textEdit.setGeometry(QtCore.QRect(518, 285, 551, 30))
        font = QtGui.QFont()
        font.setPointSize(11)
        self.textEdit.setFont(font)
        self.textEdit.setObjectName("textEdit")
        self.PBSendDispSpk = QtWidgets.QPushButton(Frame)
        self.PBSendDispSpk.setGeometry(QtCore.QRect(10, 266, 240, 31))
        self.PBSendDispSpk.setObjectName("PBSendDispSpk")
        self.CBspeak = QtWidgets.QComboBox(Frame)
        self.CBspeak.setGeometry(QtCore.QRect(517, 206, 160, 31))
        self.CBspeak.setObjectName("CBspeak")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.CBspeak.addItem("")
        self.label = QtWidgets.QLabel(Frame)
        self.label.setGeometry(QtCore.QRect(260, 216, 54, 15))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(Frame)
        self.label_2.setGeometry(QtCore.QRect(456, 216, 54, 15))
        self.label_2.setObjectName("label_2")
        self.label_3 = QtWidgets.QLabel(Frame)
        self.label_3.setGeometry(QtCore.QRect(456, 295, 54, 15))
        self.label_3.setObjectName("label_3")
        self.PBReadCard = QtWidgets.QPushButton(Frame)
        self.PBReadCard.setGeometry(QtCore.QRect(10, 335, 240, 31))
        self.PBReadCard.setObjectName("PBReadCard")
        self.PBWriteCard = QtWidgets.QPushButton(Frame)
        self.PBWriteCard.setGeometry(QtCore.QRect(10, 365, 240, 31))
        self.PBWriteCard.setObjectName("PBWriteCard")
        self.PBChangeKey = QtWidgets.QPushButton(Frame)
        self.PBChangeKey.setGeometry(QtCore.QRect(10, 395, 240, 31))
        self.PBChangeKey.setObjectName("PBChangeKey")
        self.PBSwitchOn = QtWidgets.QPushButton(Frame)
        self.PBSwitchOn.setGeometry(QtCore.QRect(10, 236, 150, 31))
        self.PBSwitchOn.setObjectName("PBSwitchOn")
        self.PBSwitchOff = QtWidgets.QPushButton(Frame)
        self.PBSwitchOff.setGeometry(QtCore.QRect(160, 236, 90, 31))
        self.PBSwitchOff.setObjectName("PBSwitchOff")
        self.PBClear = QtWidgets.QPushButton(Frame)
        self.PBClear.setGeometry(QtCore.QRect(940, 410, 131, 31))
        self.PBClear.setObjectName("PBClear")
        self.PBSetRW = QtWidgets.QPushButton(Frame)
        self.PBSetRW.setGeometry(QtCore.QRect(810, 410, 131, 31))
        self.PBSetRW.setObjectName("PBSetRW")
        self.label_4 = QtWidgets.QLabel(Frame)
        self.label_4.setGeometry(QtCore.QRect(260, 286, 54, 12))
        self.label_4.setObjectName("label_4")
        self.spinBox = QtWidgets.QSpinBox(Frame)
        self.spinBox.setGeometry(QtCore.QRect(320, 276, 100, 40))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.spinBox.setFont(font)
        self.spinBox.setMaximum(255)
        self.spinBox.setObjectName("spinBox")
        self.label_5 = QtWidgets.QLabel(Frame)
        self.label_5.setGeometry(QtCore.QRect(713, 216, 54, 15))
        self.label_5.setObjectName("label_5")
        self.textEdit_2 = QtWidgets.QTextEdit(Frame)
        self.textEdit_2.setGeometry(QtCore.QRect(771, 206, 300, 30))
        font = QtGui.QFont()
        font.setPointSize(11)
        self.textEdit_2.setFont(font)
        self.textEdit_2.setObjectName("textEdit_2")
        self.CBSwitch = QtWidgets.QComboBox(Frame)
        self.CBSwitch.setGeometry(QtCore.QRect(320, 241, 111, 31))
        self.CBSwitch.setObjectName("CBSwitch")
        self.CBSwitch.addItem("")
        self.CBSwitch.addItem("")
        self.CBSwitch.addItem("")
        self.CBSwitch.addItem("")
        self.CBSwitch.addItem("")
        self.CBSwitch.addItem("")
        self.CBSwitch.addItem("")
        self.CBSwitch.addItem("")
        self.CBSwitch.addItem("")
        self.label_6 = QtWidgets.QLabel(Frame)
        self.label_6.setGeometry(QtCore.QRect(260, 251, 54, 15))
        self.label_6.setObjectName("label_6")
        self.label_7 = QtWidgets.QLabel(Frame)
        self.label_7.setGeometry(QtCore.QRect(455, 251, 54, 15))
        self.label_7.setObjectName("label_7")
        self.spinBox_2 = QtWidgets.QSpinBox(Frame)
        self.spinBox_2.setGeometry(QtCore.QRect(518, 240, 100, 40))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.spinBox_2.setFont(font)
        self.spinBox_2.setMaximum(65535)
        self.spinBox_2.setObjectName("spinBox_2")
        self.spinBox_3 = QtWidgets.QSpinBox(Frame)
        self.spinBox_3.setGeometry(QtCore.QRect(772, 240, 100, 40))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.spinBox_3.setFont(font)
        self.spinBox_3.setMaximum(25)
        self.spinBox_3.setObjectName("spinBox_3")
        self.label_8 = QtWidgets.QLabel(Frame)
        self.label_8.setGeometry(QtCore.QRect(709, 250, 54, 15))
        self.label_8.setObjectName("label_8")
        self.label_9 = QtWidgets.QLabel(Frame)
        self.label_9.setGeometry(QtCore.QRect(260, 333, 54, 15))
        self.label_9.setObjectName("label_9")
        self.textEdit_3 = QtWidgets.QTextEdit(Frame)
        self.textEdit_3.setGeometry(QtCore.QRect(320, 323, 111, 31))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.textEdit_3.setFont(font)
        self.textEdit_3.setObjectName("textEdit_3")
        self.label_10 = QtWidgets.QLabel(Frame)
        self.label_10.setGeometry(QtCore.QRect(459, 333, 54, 15))
        self.label_10.setObjectName("label_10")
        self.CBPage = QtWidgets.QComboBox(Frame)
        self.CBPage.setGeometry(QtCore.QRect(520, 323, 111, 31))
        self.CBPage.setObjectName("CBPage")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBPage.addItem("")
        self.CBauth = QtWidgets.QComboBox(Frame)
        self.CBauth.setGeometry(QtCore.QRect(742, 323, 111, 31))
        self.CBauth.setObjectName("CBauth")
        self.CBauth.addItem("")
        self.CBauth.addItem("")
        self.label_11 = QtWidgets.QLabel(Frame)
        self.label_11.setGeometry(QtCore.QRect(660, 333, 81, 16))
        self.label_11.setObjectName("label_11")
        self.label_12 = QtWidgets.QLabel(Frame)
        self.label_12.setGeometry(QtCore.QRect(880, 333, 54, 15))
        self.label_12.setObjectName("label_12")
        self.textEdit_4 = QtWidgets.QTextEdit(Frame)
        self.textEdit_4.setGeometry(QtCore.QRect(940, 323, 131, 31))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.textEdit_4.setFont(font)
        self.textEdit_4.setObjectName("textEdit_4")
        self.label_13 = QtWidgets.QLabel(Frame)
        self.label_13.setGeometry(QtCore.QRect(260, 373, 54, 15))
        self.label_13.setObjectName("label_13")
        self.textEdit_5 = QtWidgets.QTextEdit(Frame)
        self.textEdit_5.setGeometry(QtCore.QRect(320, 355, 750, 50))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.textEdit_5.setFont(font)
        self.textEdit_5.setObjectName("textEdit_5")
        self.label_14 = QtWidgets.QLabel(Frame)
        self.label_14.setGeometry(QtCore.QRect(270, 420, 54, 12))
        self.label_14.setObjectName("label_14")
        self.textEdit_6 = QtWidgets.QTextEdit(Frame)
        self.textEdit_6.setGeometry(QtCore.QRect(320, 410, 361, 31))
        font = QtGui.QFont()
        font.setPointSize(10)
        self.textEdit_6.setFont(font)
        self.textEdit_6.setObjectName("textEdit_6")

        self.comboBox_3 = QtWidgets.QComboBox(Frame)
        self.comboBox_3.setGeometry(QtCore.QRect(690, 410, 120, 31))
        self.comboBox_3.setObjectName("comboBox_3")
        self.comboBox_3.addItem("")
        self.comboBox_3.addItem("")
        self.comboBox_3.addItem("")

        self.TEPort = QtWidgets.QTextEdit(Frame)
        self.TEPort.setGeometry(QtCore.QRect(340, 10, 71, 31))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.TEPort.setFont(font)
        self.TEPort.setObjectName("TEPort")
        self.label_15 = QtWidgets.QLabel(Frame)
        self.label_15.setGeometry(QtCore.QRect(10, 170, 110, 20))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_15.setFont(font)
        self.label_15.setObjectName("label_15")
        self.label_16 = QtWidgets.QLabel(Frame)
        self.label_16.setGeometry(QtCore.QRect(380, 170, 60, 20))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_16.setFont(font)
        self.label_16.setObjectName("label_16")
        self.textEdit_7 = QtWidgets.QTextEdit(Frame)
        self.textEdit_7.setGeometry(QtCore.QRect(126, 164, 201, 30))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.textEdit_7.setFont(font)
        self.textEdit_7.setObjectName("textEdit_7")
        self.textEdit_8 = QtWidgets.QTextEdit(Frame)
        self.textEdit_8.setGeometry(QtCore.QRect(435, 164, 80, 30))
        font = QtGui.QFont()
        font.setPointSize(12)
        self.textEdit_8.setFont(font)
        self.textEdit_8.setObjectName("textEdit_8")
        self.listWidget = QtWidgets.QListWidget(Frame)
        self.listWidget.setGeometry(QtCore.QRect(10, 450, 1061, 131))
        self.listWidget.setObjectName("listWidget")

        self.subThread = EditUIThread()   # 创建刷新UI子线程
        self.subThread.update_data.connect(self.EditUI) # 将子线程中的信号与EditUI槽函数绑定
        self.subThread.start()   # 启动子线程更新UI界面

        self.subSockListenThread=SockListenThread()
        self.subSockListenThread.Sock_data.connect(self.SockGetData)
        self.subSockListenThread.start()

        self.retranslateUi(Frame)

        self.PBSearch.clicked.connect(self.PBSearch_click)
        self.PBClear.clicked.connect(self.PBClear_click)
        self.PBSetRW.clicked.connect(self.PBSetRW_click)
        self.CBIP.currentIndexChanged.connect(self.CBIP_selectionchange)
        self.PBSendDispBeep.clicked.connect(self.PBSendDispBeep_click)
        self.PBEditpara.clicked.connect(self.PBEditpara_click)
        self.tableWidget.doubleClicked.connect(self.table_doubleClick)
        self.PBSwitchOn.clicked.connect(self.PBSwitchOn_click)
        self.PBSwitchOff.clicked.connect(self.PBSwitchOff_click)
        self.PBSendDispSpk.clicked.connect(self.PBSendDispSpk_click)
        self.PBSendDispTTS.clicked.connect(self.PBSendDispTTS_click)
        self.PBReadCard.clicked.connect(self.PBReadCard_click)
        self.PBWriteCard.clicked.connect(self.PBWriteCard_click)
        self.PBChangeKey.clicked.connect(self.PBChangeKey_click)

        QtCore.QMetaObject.connectSlotsByName(Frame)

    def retranslateUi(self, Frame):
        _translate = QtCore.QCoreApplication.translate
        Frame.setWindowTitle(_translate("Frame", "RFID网络读卡器测试工具"))
        self.PBSearch.setText(_translate("Frame", "搜索所有在线设备"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("Frame", "设备编号"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("Frame", "设备IP"))
        item = self.tableWidget.horizontalHeaderItem(2)
        item.setText(_translate("Frame", "子网掩码"))
        item = self.tableWidget.horizontalHeaderItem(3)
        item.setText(_translate("Frame", "通讯端口"))
        item = self.tableWidget.horizontalHeaderItem(4)
        item.setText(_translate("Frame", "设备网关"))
        item = self.tableWidget.horizontalHeaderItem(5)
        item.setText(_translate("Frame", "网关MAC"))
        item = self.tableWidget.horizontalHeaderItem(6)
        item.setText(_translate("Frame", "目标服务器IP"))
        item = self.tableWidget.horizontalHeaderItem(7)
        item.setText(_translate("Frame", "服务器MAC"))
        item = self.tableWidget.horizontalHeaderItem(8)
        item.setText(_translate("Frame", "参数标识"))
        item = self.tableWidget.horizontalHeaderItem(9)
        item.setText(_translate("Frame", "参数"))
        item = self.tableWidget.horizontalHeaderItem(10)
        item.setText(_translate("Frame", "出厂序号"))
        item = self.tableWidget.horizontalHeaderItem(11)
        item.setText(_translate("Frame", "STC系列 设备MAC"))
        item = self.tableWidget.horizontalHeaderItem(12)
        item.setText(_translate("Frame", "唯一硬件序号"))
        item = self.tableWidget.horizontalHeaderItem(13)
        item.setText(_translate("Frame", "CH系列 设备MAC"))
        self.PBEditpara.setText(_translate("Frame", "修改选定设备的网络参数"))
        self.PBSendDispBeep.setText(_translate("Frame", "驱动设备显示文字及蜂鸣响声"))
        self.PBSendDispTTS.setText(_translate("Frame", "驱动设备显示文字+TTS语音+继电器"))
        self.CBbeep.setItemText(0, _translate("Frame", "短滴一声"))
        self.CBbeep.setItemText(1, _translate("Frame", "短滴两声"))
        self.CBbeep.setItemText(2, _translate("Frame", "短滴三声"))
        self.CBbeep.setItemText(3, _translate("Frame", "长鸣一声"))
        self.CBbeep.setItemText(4, _translate("Frame", "长鸣两声"))
        self.CBbeep.setItemText(5, _translate("Frame", "长鸣三声"))
        self.CBbeep.setItemText(6, _translate("Frame", "一长一短"))
        self.CBbeep.setItemText(7, _translate("Frame", "一长两短"))
        self.CBbeep.setItemText(8, _translate("Frame", "一长三短"))
        self.CBbeep.setItemText(9, _translate("Frame", "两长一短"))
        self.CBbeep.setItemText(10, _translate("Frame", "两长两短"))
        self.CBbeep.setItemText(11, _translate("Frame", "两长三短"))
        self.textEdit.setPlaceholderText(_translate("Frame", "欢迎您使用我们的网络读卡器!"))
        self.PBSendDispSpk.setText(_translate("Frame", "驱动设备显示文字+组合语音+继电器"))
        self.CBspeak.setItemText(0, _translate("Frame", "0  零"))
        self.CBspeak.setItemText(1, _translate("Frame", "1  壹"))
        self.CBspeak.setItemText(2, _translate("Frame", "2  贰"))
        self.CBspeak.setItemText(3, _translate("Frame", "3  叁"))
        self.CBspeak.setItemText(4, _translate("Frame", "4  肆"))
        self.CBspeak.setItemText(5, _translate("Frame", "5  伍"))
        self.CBspeak.setItemText(6, _translate("Frame", "6  陆"))
        self.CBspeak.setItemText(7, _translate("Frame", "7  柒"))
        self.CBspeak.setItemText(8, _translate("Frame", "8  捌"))
        self.CBspeak.setItemText(9, _translate("Frame", "9  玖"))
        self.CBspeak.setItemText(10, _translate("Frame", "10 拾"))
        self.CBspeak.setItemText(11, _translate("Frame", "11 佰"))
        self.CBspeak.setItemText(12, _translate("Frame", "12 仟"))
        self.CBspeak.setItemText(13, _translate("Frame", "13 万"))
        self.CBspeak.setItemText(14, _translate("Frame", "14 点"))
        self.CBspeak.setItemText(15, _translate("Frame", "15 分"))
        self.CBspeak.setItemText(16, _translate("Frame", "16 角"))
        self.CBspeak.setItemText(17, _translate("Frame", "17 元"))
        self.CBspeak.setItemText(18, _translate("Frame", "18 设备故障,请看屏幕提示"))
        self.CBspeak.setItemText(19, _translate("Frame", "19 无效卡"))
        self.CBspeak.setItemText(20, _translate("Frame", "20 非本单位卡"))
        self.CBspeak.setItemText(21, _translate("Frame", "21 此卡类型不许可"))
        self.CBspeak.setItemText(22, _translate("Frame", "22 此卡已挂失"))
        self.CBspeak.setItemText(23, _translate("Frame", "23 卡已过期"))
        self.CBspeak.setItemText(24, _translate("Frame", "24 剩余次数"))
        self.CBspeak.setItemText(25, _translate("Frame", "25 余额不足"))
        self.CBspeak.setItemText(26, _translate("Frame", "26 次数不足"))
        self.CBspeak.setItemText(27, _translate("Frame", "27 密码错误"))
        self.CBspeak.setItemText(28, _translate("Frame", "28 记录已满"))
        self.CBspeak.setItemText(29, _translate("Frame", "29 本餐"))
        self.CBspeak.setItemText(30, _translate("Frame", "30 当天"))
        self.CBspeak.setItemText(31, _translate("Frame", "31 累计消费已超出"))
        self.CBspeak.setItemText(32, _translate("Frame", "32 累计次数已超出"))
        self.CBspeak.setItemText(33, _translate("Frame", "33 卡号"))
        self.CBspeak.setItemText(34, _translate("Frame", "34 机号"))
        self.CBspeak.setItemText(35, _translate("Frame", "35 余额"))
        self.CBspeak.setItemText(36, _translate("Frame", "36 本次消费"))
        self.CBspeak.setItemText(37, _translate("Frame", "37 本次加款"))
        self.CBspeak.setItemText(38, _translate("Frame", "38 不允许在此时段刷卡"))
        self.CBspeak.setItemText(39, _translate("Frame", "39 消费"))
        self.CBspeak.setItemText(40, _translate("Frame", "40 充值"))
        self.CBspeak.setItemText(41, _translate("Frame", "41 成功"))
        self.CBspeak.setItemText(42, _translate("Frame", "42 失败"))
        self.CBspeak.setItemText(43, _translate("Frame", "43 请输入密码"))
        self.CBspeak.setItemText(44, _translate("Frame", "44 请重新刷卡"))
        self.CBspeak.setItemText(45, _translate("Frame", "45 取餐"))
        self.CBspeak.setItemText(46, _translate("Frame", "46 没有订餐"))
        self.CBspeak.setItemText(47, _translate("Frame", "47 早上好"))
        self.CBspeak.setItemText(48, _translate("Frame", "48 中午好"))
        self.CBspeak.setItemText(49, _translate("Frame", "49 下午好"))
        self.CBspeak.setItemText(50, _translate("Frame", "50 晚上好"))
        self.CBspeak.setItemText(51, _translate("Frame", "51 已充值"))
        self.CBspeak.setItemText(52, _translate("Frame", "52 已取餐"))
        self.CBspeak.setItemText(53, _translate("Frame", "53 谢谢"))
        self.CBspeak.setItemText(54, _translate("Frame", "54 已消费"))
        self.CBspeak.setItemText(55, _translate("Frame", "55 刷卡"))
        self.CBspeak.setItemText(56, _translate("Frame", "56 订餐"))
        self.CBspeak.setItemText(57, _translate("Frame", "57 次"))
        self.label.setText(_translate("Frame", "蜂鸣响声:"))
        self.label_2.setText(_translate("Frame", "组合语音:"))
        self.label_3.setText(_translate("Frame", "显示文字:"))
        self.PBReadCard.setText(_translate("Frame", "驱动读写器读取指定扇区数据"))
        self.PBWriteCard.setText(_translate("Frame", "驱动读写器写数据到指定扇区"))
        self.PBChangeKey.setText(_translate("Frame", "驱动读写器更改指定扇区密码"))
        self.PBSwitchOn.setText(_translate("Frame", "驱动设备开启继电器"))
        self.PBSwitchOff.setText(_translate("Frame", "关闭继电器"))
        self.PBClear.setText(_translate("Frame", "清除下栏提示信息"))
        self.PBSetRW.setText(_translate("Frame", "设置主动读写扇区"))
        self.label_4.setText(_translate("Frame", "显示延时:"))
        self.label_5.setText(_translate("Frame", "TTS语音:"))
        self.textEdit_2.setPlaceholderText(_translate("Frame", "欢迎您使用我们的网络读卡器!"))
        self.CBSwitch.setItemText(0, _translate("Frame", "全部继电器"))
        self.CBSwitch.setItemText(1, _translate("Frame", "1 号继电器"))
        self.CBSwitch.setItemText(2, _translate("Frame", "2 号继电器"))
        self.CBSwitch.setItemText(3, _translate("Frame", "3 号继电器"))
        self.CBSwitch.setItemText(4, _translate("Frame", "4 号继电器"))
        self.CBSwitch.setItemText(5, _translate("Frame", "5 号继电器"))
        self.CBSwitch.setItemText(6, _translate("Frame", "6 号继电器"))
        self.CBSwitch.setItemText(7, _translate("Frame", "7 号继电器"))
        self.CBSwitch.setItemText(8, _translate("Frame", "8 号继电器"))
        self.label_6.setText(_translate("Frame", "继电器号:"))
        self.label_7.setText(_translate("Frame", "开启延时:"))
        self.label_8.setText(_translate("Frame", "语音音量:"))
        self.label_9.setText(_translate("Frame", "IC卡卡号:"))
        self.textEdit_3.setPlaceholderText(_translate("Frame", "00000000"))
        self.label_10.setText(_translate("Frame", "选择扇区:"))
        self.CBPage.setItemText(0, _translate("Frame", "第  0 扇区"))
        self.CBPage.setItemText(1, _translate("Frame", "第  1 扇区"))
        self.CBPage.setItemText(2, _translate("Frame", "第  2 扇区"))
        self.CBPage.setItemText(3, _translate("Frame", "第  3 扇区"))
        self.CBPage.setItemText(4, _translate("Frame", "第  4 扇区"))
        self.CBPage.setItemText(5, _translate("Frame", "第  5 扇区"))
        self.CBPage.setItemText(6, _translate("Frame", "第  6 扇区"))
        self.CBPage.setItemText(7, _translate("Frame", "第  7 扇区"))
        self.CBPage.setItemText(8, _translate("Frame", "第  8 扇区"))
        self.CBPage.setItemText(9, _translate("Frame", "第  9 扇区"))
        self.CBPage.setItemText(10, _translate("Frame", "第 10 扇区"))
        self.CBPage.setItemText(11, _translate("Frame", "第 11 扇区"))
        self.CBPage.setItemText(12, _translate("Frame", "第 12 扇区"))
        self.CBPage.setItemText(13, _translate("Frame", "第 13 扇区"))
        self.CBPage.setItemText(14, _translate("Frame", "第 14 扇区"))
        self.CBPage.setItemText(15, _translate("Frame", "第 15 扇区"))
        self.CBauth.setItemText(0, _translate("Frame", "B 密码"))
        self.CBauth.setItemText(1, _translate("Frame", "A 密码"))
        self.label_11.setText(_translate("Frame", "密码认证类型:"))
        self.label_12.setText(_translate("Frame", "卡片密码:"))
        self.textEdit_4.setPlaceholderText(_translate("Frame", "FFFFFFFFFFFF"))
        self.label_13.setText(_translate("Frame", "扇区数据:"))
        self.textEdit_5.setPlaceholderText(_translate("Frame", "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00"))
        self.label_14.setText(_translate("Frame", "新密码:"))
        self.textEdit_6.setPlaceholderText(_translate("Frame", "FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF"))
        self.comboBox_3.setItemText(0, _translate("Frame", "只修改A密码"))
        self.comboBox_3.setItemText(1, _translate("Frame", "修改A密码及控制位"))
        self.comboBox_3.setItemText(2, _translate("Frame", "修改AB密码及控制位"))
        self.TEPort.setPlaceholderText(_translate("Frame", "39169"))
        self.label_15.setText(_translate("Frame", "设备IP及端口:"))
        self.label_16.setText(_translate("Frame", "机 号:"))
        self.textEdit_7.setPlaceholderText(_translate("Frame", "192.168.1.228:39169"))

    def EditUI(self,Dispinf):
        if (EditUiEn==1):
            self.textEdit_7.setText(RemortIPort)
        elif(EditUiEn==2):
            self.ListAddItem(Dispinf)

    def SockGetData(self,dispcode,Getdata):
        if(dispcode==1):
            self.textEdit_7.setText(Getdata)
        elif(dispcode==2):
            self.ListAddItem(Getdata)
        elif (dispcode == 3):
            FieldsList = Getdata.split(',')
            rowPosition = self.tableWidget.rowCount()
            self.tableWidget.insertRow(rowPosition)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[0])
            self.tableWidget.setItem(rowPosition, 0, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[1])
            self.tableWidget.setItem(rowPosition, 1, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[2])
            self.tableWidget.setItem(rowPosition, 2, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[3])
            self.tableWidget.setItem(rowPosition, 3, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[4])
            self.tableWidget.setItem(rowPosition, 4, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[5])
            self.tableWidget.setItem(rowPosition, 5, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[6])
            self.tableWidget.setItem(rowPosition, 6, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[7])
            self.tableWidget.setItem(rowPosition, 7, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[8])
            self.tableWidget.setItem(rowPosition, 8, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[9])
            self.tableWidget.setItem(rowPosition, 9, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[10])
            self.tableWidget.setItem(rowPosition, 10, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[11])
            self.tableWidget.setItem(rowPosition, 11, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[12])
            self.tableWidget.setItem(rowPosition, 12, NewItem)
            NewItem = QtWidgets.QTableWidgetItem(FieldsList[13])
            self.tableWidget.setItem(rowPosition, 13, NewItem)
            self.tableWidget.resizeColumnsToContents()
        elif (dispcode == 4):  #显示卡号
            self.textEdit_8.setText(Getdata)
        elif (dispcode == 5): #显示读卡数据
            self.textEdit_5.setText(Getdata)

    def table_doubleClick(self):
        currentrow = self.tableWidget.currentRow()  # 获取当前鼠标点击了第几行
        if (currentrow >= 0):
            DevNo= self.tableWidget.item(currentrow, 0).text()
            DEvIp = self.tableWidget.item(currentrow, 1).text()
            DevPort = self.tableWidget.item(currentrow, 3).text()
            self.textEdit_7.setPlainText(DEvIp+':'+DevPort)
            self.textEdit_8.setPlainText(DevNo)

    def PBEditpara_click(self):
        currentrow = self.tableWidget.currentRow()  # 获取当前鼠标点击了第几行
        if(currentrow>=0):
            DevNo=int(self.tableWidget.item(currentrow, 0).text())
            DEvIp = self.tableWidget.item(currentrow, 1).text()
            DevMask = self.tableWidget.item(currentrow, 2).text()
            DevPort = int(self.tableWidget.item(currentrow, 3).text())
            DevGetway = self.tableWidget.item(currentrow, 4).text()
            GetwayMac = self.tableWidget.item(currentrow, 5).text()
            ServeIp = self.tableWidget.item(currentrow, 6).text()
            ServerMac = self.tableWidget.item(currentrow, 7).text()
            Search = self.tableWidget.item(currentrow, 8).text()
            Beep = self.tableWidget.item(currentrow, 9).text()
            SerialNum = self.tableWidget.item(currentrow, 10).text()

            sdata=bytes([eval('0xF9')])         #1字节指令码
            try:
                FieldsList = DEvIp.split('.')
                HexStr='%02X%02X%02X%02X' % (int(FieldsList[0]),int(FieldsList[1]),int(FieldsList[2]),int(FieldsList[3]))    #4字节设备IP
                sdata=sdata+bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备IP地址输入错误!")
                return

            try:
                FieldsList = DevMask.split('.')
                HexStr='%02X%02X%02X%02X' % (int(FieldsList[0]),int(FieldsList[1]),int(FieldsList[2]),int(FieldsList[3]))    #4字节设备子网掩码
                sdata=sdata+bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备子网掩码输入错误!")
                return

            try:
                FieldsList = ServeIp.split('.')
                HexStr='%02X%02X%02X%02X' % (int(FieldsList[0]),int(FieldsList[1]),int(FieldsList[2]),int(FieldsList[3]))    #4字节设备远程服务器IP
                sdata=sdata+bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备远程服务器IP输入错误!")
                return

            try:
                FieldsList = ServerMac.split('-')
                HexStr=FieldsList[0]+FieldsList[1]+FieldsList[2]+FieldsList[3]+FieldsList[4]+FieldsList[5]                   #6字节设备远程服务器MAC
                sdata=sdata+bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备远程服务器MAC输入错误!")
                return

            try:
                FieldsList = DevGetway.split('.')
                HexStr='%02X%02X%02X%02X' % (int(FieldsList[0]),int(FieldsList[1]),int(FieldsList[2]),int(FieldsList[3]))    #4字节设备网关
                sdata=sdata+bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备网关IP输入错误!")
                return

            try:
                FieldsList = GetwayMac.split('-')
                HexStr=FieldsList[0]+FieldsList[1]+FieldsList[2]+FieldsList[3]+FieldsList[4]+FieldsList[5]                  #6字节设备网关MAC
                sdata=sdata+bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备网关MAC输入错误!")
                return

            try:
                HexStr='%02X%02X' % (DevNo % 256, DevNo // 256)  #2字节机号
                sdata = sdata + bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备机号输入错误!")
                return

            try:
                HexStr='%02X%02X' % (DevPort % 256, DevPort // 256)  #2字节端口号
                sdata = sdata + bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备端口输入错误!")
                return

            try:
                FieldsList = SerialNum.split('-')
                HexStr=FieldsList[0]+FieldsList[1]+FieldsList[2]+FieldsList[3]    #4字节设备网出厂序号
                sdata=sdata+bytes.fromhex(HexStr)
            except:
                self.ListAddItem("设备出厂序号输入错误!")
                return

            try:
                para1=Search[0:5]
                para2=int(Search[5:6])
                para2=para2+(int(Search[7:8])*2)
                para2 = para2 +(int(Search[6:7])*4)
                para2 = ('000'+bin(para2))[-3:]
                sdata = sdata + bytes([int(para1+para2,base=2)])  #参数标识字节每位说明  bit7:卡在隔10秒重发,bit6:卡在隔2秒重发,bit5:卡在隔1秒重发,bit4:卡离开发信息,bit3:DHCP,bit2:刷卡响声,bit1:网关MAC自动获取,bit0:远程服务器MAC自动获取
            except:
                self.ListAddItem("参数标识输入错误")
                return

            sdata = sdata + bytes.fromhex('55AA6699')

            s.sendto(sdata, ('255.255.255.255', Bindprot))  # 发送设置读卡器网络参数的广播指令
            SendInf = 'SendTo: 255.255.255.255:'+str(Bindprot) + '    Data:'
            for num in range(0, len(sdata)):
                SendInf = SendInf + '%02X ' % (sdata[num])
            self.ListAddItem(SendInf)

    def PBClear_click(self):
        self.listWidget.clear()

    def ListAddItem(self,itemstr):
        if self.listWidget.count() > 10:
            self.listWidget.clear()
        self.listWidget.addItem(itemstr)
        self.listWidget.scrollToBottom()
        seleid = self.listWidget.count() - 1
        self.listWidget.item(seleid).setSelected(True)

    def PBSearch_click(self):
        global LastBuf
        LastBuf = bytes(9)
        self.tableWidget.setRowCount(0)     #清空表格内现有记录
        self.textEdit_7.setPlainText('255.255.255.255:39169')
        sdata = bytes([166])  # 搜索在线设备的指令码
        s.sendto(sdata, ('255.255.255.255', Bindprot))  # 发送搜索同网段内所有在线设备的广播指令
        self.ListAddItem("SendTo:255.255.255.255:"+str(Bindprot)+"   Data:A6")

    def CBIP_selectionchange(self):
        global listen
        global s
        if listen==1:
            listen=0
            s.close()
        if changip == 1:
            try:
                Bindip = self.CBIP.currentText()
                Bindprot = int(self.TEPort.toPlainText())
                s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
                s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
                s.bind((Bindip, Bindprot))

                self.subSockListenThread = SockListenThread()
                self.subSockListenThread.Sock_data.connect(self.SockGetData)
                self.subSockListenThread.start()
                listen = 1

                self.ListAddItem("Socket is bind to :" + Bindip + ":" + str(Bindprot))
            except:
                listen = 0
                self.ListAddItem("Socket is bind to :" + Bindip + ":" + str(Bindprot) + " failure!")

    def PBSendDispBeep_click(self):
        FieldsList = self.textEdit_7.toPlainText().split(':')
        Remoip=FieldsList[0]
        Reprot=int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        dispinf=self.textEdit.toPlainText()+'                                    '                  #加空格是为了显示全屏
        SendDispBeep(dispinf, (Remoip, Reprot),DevNo)

    def PBSwitchOff_click(self):
        FieldsList = self.textEdit_7.toPlainText().split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo=int(self.textEdit_8.toPlainText())
        SendSwitch(DevNo,(Remoip, Reprot),0)

    def PBSwitchOn_click(self):
        FieldsList = self.textEdit_7.toPlainText().split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        SendSwitch(DevNo,(Remoip, Reprot), 1)

    def PBSendDispTTS_click(self):
        FieldsList = self.textEdit_7.toPlainText().split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        dispinf = self.textEdit.toPlainText() + '                                    '  # 加空格是为了显示全屏
        SendDispTTS(dispinf, (Remoip, Reprot), DevNo)

    def PBSendDispSpk_click(self):
        FieldsList = self.textEdit_7.toPlainText().split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        dispinf = self.textEdit.toPlainText() + '                                    '  # 加空格是为了显示全屏
        SendDispSpk(dispinf, (Remoip, Reprot), DevNo)

    def PBReadCard_click(self):
        global   LastBuf
        LastBuf = bytes(9)
        self.textEdit_5.setPlainText('')
        FieldsList = self.textEdit_7.toPlainText().split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        CardNo=self.textEdit_3.toPlainText()                # 16进制卡号
        sector = self.CBPage.currentIndex()                 # 读写扇区号
        auth = self.CBauth.currentIndex()                   # 密码认证方式
        keys = bytes.fromhex(ui.textEdit_4.toPlainText())   # 认证密码
        if (len(keys) == 6):
            ReadCardInf(DevNo, (Remoip, Reprot), CardNo, sector, auth, keys)
        else:
            self.ListAddItem("卡密码输入错误!")

    def PBWriteCard_click(self):
        global LastBuf
        LastBuf = bytes(9)
        FieldsList = self.textEdit_7.toPlainText().split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        CardNo = self.textEdit_3.toPlainText()  # 16进制卡号
        sector = self.CBPage.currentIndex()  # 读写扇区号
        auth = self.CBauth.currentIndex()  # 密码认证方式
        keys = bytes.fromhex(ui.textEdit_4.toPlainText())  # 认证密码
        WriteBuf = bytes.fromhex(self.textEdit_5.toPlainText())             # 48字节写卡数据
        if (len(keys) != 6):
            self.ListAddItem("卡密码输入错误!")
            return
        if (len(WriteBuf) < 48):
            self.ListAddItem("写卡数据不足48字节!")
            return
        WriteCard(DevNo, (Remoip, Reprot), CardNo, sector, auth,keys,WriteBuf)

    def PBChangeKey_click(self):
        self.Dialog = MyDialog()
        self.Dialog.sig.connect(self.Changekey)
        self.Dialog.start()

    def Changekey(self, obj):
        res = QMessageBox.question(None, "警告", "     您确定要继续执行修改卡密码及控制位的操作吗?如确定修改请务必记住卡的新密码,否则卡片将报废!", QMessageBox.Yes | QMessageBox.No)
        if (QMessageBox.Yes == res):
            global LastBuf
            LastBuf = bytes(9)
            FieldsList = self.textEdit_7.toPlainText().split(':')
            Remoip = FieldsList[0]
            Reprot = int(FieldsList[1])
            DevNo = int(self.textEdit_8.toPlainText())
            CardNo = self.textEdit_3.toPlainText()              # 16进制卡号
            sector = self.CBPage.currentIndex()                 # 读写扇区号
            auth = self.CBauth.currentIndex()                   # 密码认证方式
            auth=auth+self.comboBox_3.currentIndex()            # 密码修改方式
            keys = bytes.fromhex(self.textEdit_4.toPlainText()) # 认证密码
            NewKeyBuf = bytes.fromhex(self.textEdit_6.toPlainText())  # 16字节新卡密码
            if (len(keys) != 6):
                self.ListAddItem("卡密码输入错误!")
                return
            if (len(NewKeyBuf) != 16):
                self.ListAddItem("新卡密码输入错误!")
                return
            ChangCardKey(DevNo, (Remoip, Reprot), CardNo, sector, auth, keys, NewKeyBuf)

    def PBSetRW_click(self):
        self.Dialog = MyDialog()
        self.Dialog.sig.connect(self.SetRW)
        self.Dialog.start()

    def SetRW(self, obj):
        global LastBuf
        LastBuf = bytes(9)
        FieldsList = self.textEdit_7.toPlainText().split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        DevNoHexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
        sector = self.CBPage.currentIndex()     # 读写扇区号
        auth = self.CBauth.currentIndex()       # 密码认证方式
        keys = bytes.fromhex(self.textEdit_4.toPlainText())  # 认证密码
        if (len(keys) != 6):
            self.ListAddItem("卡密码输入错误!")
            return

        res = QMessageBox.question(None, "提示", "     按 Yes 键把读写器设为主动读取第 "+str(self.CBPage.currentIndex())+" 扇区数据,按 No 键将读写器设为只读卡号不读扇区数据。", QMessageBox.Yes | QMessageBox.No)
        if (QMessageBox.No == res):
            sdata = bytes([eval('0x4B')])    # 4B是指令码
            sdata = sdata + bytes.fromhex(DevNoHexStr)  # 2字节机号
            sdata = sdata +bytes([0])                   # 读0个扇区数据
            sdata = sdata + bytes.fromhex("55AA6699")   # 4字节确认码
            s.sendto(sdata, (Remoip, Reprot))
            SendInf = 'SendTo: %s:%s' % (Remoip, Reprot) + '    Data:'
            for num in range(0, len(sdata)):
                SendInf = SendInf + '%02X ' % (sdata[num])
            self.ListAddItem(SendInf)
        else:
            sdata = bytes([eval('0x4B')])          # 4B是指令码
            sdata = sdata + bytes.fromhex("0000")  # 2字节机号
            sdata = sdata + bytes([1])             # 主动读取的扇区数,如果要开通几个扇区这里就填几
            if(auth==0):
                sector=sector + 128
            sdata=sdata+ bytes([sector])+keys      #1字节的扇区号及密码认证类型 + 6字节卡认证密码 ,如果读多个扇区也按此结构加入,可以开通全部的16个扇区
            sdata = sdata + bytes.fromhex("55AA6699")   # 4字节确认码
            s.sendto(sdata, (Remoip, Reprot))
            SendInf = 'SendTo: %s:%s' % (Remoip, Reprot) + '    Data:'
            for num in range(0, len(sdata)):
                SendInf = SendInf + '%02X ' % (sdata[num])
            self.ListAddItem(SendInf)

#获取电脑钟---------------------------------------------------------------------------
def get_time():
   st = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
   st=st[0:16]
   return st

#接收到数据包后向设备发确认信息,否则设备会重发三次--------------------------------------------
def DisableSendAge(data,addr):
   global dispinf
   global EditUiEn
   #105是指令码+接收到的信息前8个字节
   sdata=bytes([105,data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[8]])
   s.sendto(sdata,addr)
   SendInf = 'SendTo: %s:%s' % addr+'    Data:'
   for num in range(0,len(sdata)):
       SendInf=SendInf + '%02X ' % (sdata[num])
   EditUiEn = 2
   dispinf = SendInf
   ui.subThread.start()

# 向读卡器发送显示及蜂鸣响声----------------------------------------------------------------
def SendDispBeep(DispStr,addr,DevNo):
    global dispinf
    global EditUiEn
    HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)   # 2字节机号
    DispStr = DispStr[0:34]
    disb = bytes(DispStr, encoding='gbk')           # 将要显示的文字转bytes
    comb = bytes([eval('0x5A')])                    # 5A是指令码
    comb = comb + bytes.fromhex(HexStr)             # 2字节机号
    comb = comb +bytes([ui.CBbeep.currentIndex()])  #1字节蜂鸣代码
    comb = comb + bytes([ui.spinBox.value()])       #1字节显示时长
    sdata = comb + disb                             #34字节显示文字
    s.sendto(sdata, addr)
    SendInf = 'SendTo: %s:%s' % addr + '    Data:'
    for num in range(0, len(sdata)):
        SendInf = SendInf + '%02X ' % (sdata[num])
    EditUiEn = 2
    dispinf = SendInf
    ui.subThread.start()

# 向读卡器发送显示+继电器+固定组合语音-------------------------------------------------------
def SendDispSpk(DispStr,addr,DevNo):
    global dispinf
    global EditUiEn
    DevNoHexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
    DelayTime = ui.spinBox_2.value()
    DelHexStr = '%02X%02X' % (DelayTime % 256, DelayTime // 256)  # 2字节延时

    disb = bytes(DispStr, encoding='gbk')  # 将要显示的文字转bytes

    Spkb = bytes([55, 41, 53])  # 固定组合语音代码,取值请查看通讯协议说明,一次最大取值21条
    Spkl = len(Spkb)            # 语音代码条数

    sufb = bytes([eval('0x55'), eval('0xaa'), eval('0x66'), eval('0x99')])  # 固定的抗干扰后缀

    comb = bytes([eval('0x5B')])                    # 5B是指令码
    comb = comb + bytes.fromhex(DevNoHexStr)        # 2字节机号
    comb = comb + bytes([ui.CBbeep.currentIndex()]) # 1字节蜂鸣代码
    comb = comb + bytes([eval('0xF0')])             # 1字节继电器代码
    comb = comb + bytes.fromhex(DelHexStr)          # 2字节继电器延时
    comb = comb + bytes([ui.spinBox.value()])       # 1字节显示时长
    comb = comb + bytes([0, 36, Spkl])              # 1字节显示起始位+1字节显示长度+1语音长度
    sdata = comb + disb[0:36] + Spkb + sufb

    s.sendto(sdata, addr)
    SendInf = 'SendTo: %s:%s' % addr + '    Data:'
    for num in range(0, len(sdata)):
        SendInf = SendInf + '%02X ' % (sdata[num])
    EditUiEn = 2
    dispinf = SendInf
    ui.subThread.start()

# 向读卡器发送显示+继电器+TTS语音-------------------------------------------------------
def SendDispTTS(DispStr,addr,DevNo):
    global dispinf
    global EditUiEn
    DevNoHexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)          # 2字节机号
    DelayTime = ui.spinBox_2.value()
    DelHexStr = '%02X%02X' % (DelayTime % 256, DelayTime // 256)    # 2字节延时
    voice = ui.spinBox_3.value()  #语音大小,最大声音值16
    if(voice>16):
        voice=16

    disb = bytes(DispStr, encoding='gbk')       # 将要显示的文字转bytes

    SpkStr = '[v'+str(voice)+']'+ui.textEdit_2.toPlainText()      # 要播报的TTS语音,[v10]表示音量,取值0-16,可放置字符串的任意地方,一次最多126个字节
    Spkb = bytes(SpkStr, encoding='gbk')        # 将要播报的TTS语音转bytes,
    Spkl = len(Spkb)  # TTS语音长度

    sufb = bytes([eval('0x55'), eval('0xaa'), eval('0x66'), eval('0x99')])  # 固定的抗干扰后缀

    comb = bytes([eval('0x5C')])                    # 5C是指令码
    comb = comb + bytes.fromhex(DevNoHexStr)        # 2字节机号
    comb = comb + bytes([ui.CBbeep.currentIndex()]) # 1字节蜂鸣代码
    comb = comb + bytes([eval('0xF0')])             #1字节继电器代码
    comb = comb + bytes.fromhex(DelHexStr)          #2字节继电器延时
    comb = comb + bytes([ui.spinBox.value()])       # 1字节显示时长
    comb = comb + bytes([0,34,Spkl])                # 1字节显示起始位+1字节显示长度+1语音长度
    sdata = comb + disb[0:34] + Spkb + sufb
    s.sendto(sdata, addr)

    SendInf = 'SendTo: %s:%s' % addr + '    Data:'
    for num in range(0, len(sdata)):
        SendInf = SendInf + '%02X ' % (sdata[num])
    EditUiEn = 2
    dispinf = SendInf
    ui.subThread.start()

# 向读卡器发送开、关继电器指令----------------------------------------------------------------
def SendSwitch(DevNo,addr,OnOff):
    global dispinf
    global EditUiEn
    HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)   # 2字节机号
    sdata = bytes([eval('0x78')])                       # 78是指令码
    sdata = sdata + bytes.fromhex(HexStr)               # 2字节机号
    if(OnOff==1):       #开继电器
        if(ui.CBSwitch.currentIndex()==0):
            sdata = sdata +bytes([eval('0xF0')])
        elif(ui.CBSwitch.currentIndex()==1):
            sdata = sdata +bytes([eval('0xF1')])
        elif (ui.CBSwitch.currentIndex() == 2):
            sdata = sdata +bytes([eval('0xF2')])
        elif (ui.CBSwitch.currentIndex() == 3):
            sdata = sdata +bytes([eval('0xF3')])
        elif (ui.CBSwitch.currentIndex() == 4):
            sdata = sdata +bytes([eval('0xF4')])
        elif (ui.CBSwitch.currentIndex() == 5):
            sdata = sdata +bytes([eval('0xF5')])
        elif (ui.CBSwitch.currentIndex() == 6):
            sdata = sdata +bytes([eval('0xF6')])
        elif (ui.CBSwitch.currentIndex() == 7):
            sdata = sdata +bytes([eval('0xF7')])
        else:
            sdata = sdata +bytes([eval('0xF8')])
    else:           #关继电器
        if (ui.CBSwitch.currentIndex() == 0):
            sdata = sdata +bytes([eval('0xE0')])
        elif (ui.CBSwitch.currentIndex() == 1):
            sdata = sdata +bytes([eval('0xE1')])
        elif (ui.CBSwitch.currentIndex() == 2):
            sdata = sdata +bytes([eval('0xE2')])
        elif (ui.CBSwitch.currentIndex() == 3):
            sdata = sdata +bytes([eval('0xE3')])
        elif (ui.CBSwitch.currentIndex() == 4):
            sdata = sdata +bytes([eval('0xE4')])
        elif (ui.CBSwitch.currentIndex() == 5):
            sdata = sdata +bytes([eval('0xE5')])
        elif (ui.CBSwitch.currentIndex() == 6):
            sdata = sdata +bytes([eval('0xE6')])
        elif (ui.CBSwitch.currentIndex() == 7):
            sdata = sdata +bytes([eval('0xE7')])
        else:
            sdata = sdata +bytes([eval('0xE8')])

    DelayTime=ui.spinBox_2.value()
    HexStr = '%02X%02X' % (DelayTime % 256, DelayTime // 256)  # 2字节延时
    sdata = sdata + bytes.fromhex(HexStr)

    s.sendto(sdata, addr)
    SendInf = 'SendTo: %s:%s' % addr + '    Data:'
    for num in range(0, len(sdata)):
        SendInf = SendInf + '%02X ' % (sdata[num])
    EditUiEn = 2
    dispinf = SendInf
    ui.subThread.start()

# 向读写器发送读扇区内数据的指令---------------------------------------------------------
def ReadCardInf(DevNo, addr,CardNo,sector,auth,keys):
    global dispinf
    global EditUiEn
    HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
    sdata = bytes([eval('0x3B')])           # 3B是指令码
    sdata = sdata + bytes.fromhex(HexStr)   # 2字节机号
    sdata = sdata + bytes([1])              # 1字节扇区个数
    sdata = sdata + bytes.fromhex(CardNo)   # 4字节16进制卡号 00000000 表示可操作任意卡
    sdata = sdata + bytes([sector])         # 1字节扇区号
    sdata = sdata + bytes([auth])           # 1字节密码认证方式
    sdata = sdata + keys                    # 6字节密码
    s.sendto(sdata, addr)
    dispinf = 'SendTo: %s:%s' % addr + '    Data:'
    for num in range(0, len(sdata)):
        dispinf = dispinf + '%02X ' % (sdata[num])
    EditUiEn = 2
    ui.subThread.start()

# 向读写器发送写信息到指定扇区的指令---------------------------------------------------------
def WriteCard(DevNo, addr,CardNo,sector,auth,keys,WriteBuf):
    global dispinf
    global EditUiEn
    HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
    sdata = bytes([eval('0x3D')])           # 3D是指令码
    sdata = sdata + bytes.fromhex(HexStr)   # 2字节机号
    sdata = sdata + bytes([1])              # 1字节扇区个数
    sdata = sdata + bytes.fromhex(CardNo)   # 4字节16进制卡号 00000000 表示可操作任意卡
    sdata = sdata + bytes([sector])         # 1字节扇区号
    sdata = sdata + bytes([auth])           # 1字节密码认证方式
    sdata = sdata +keys                     # 6字节卡密码
    sdata = sdata + WriteBuf                # 48字节写卡数据
    sdata = sdata + bytes.fromhex("55AA6699")  # 4字节防错

    s.sendto(sdata, addr)
    dispinf = 'SendTo: %s:%s' % addr + '    Data:'
    for num in range(0, len(sdata)):
        dispinf = dispinf + '%02X ' % (sdata[num])
    EditUiEn = 2
    ui.subThread.start()

# 向读写器发送更改指定扇区密码的指令---------------------------------------------------------
def ChangCardKey(DevNo, addr,CardNo,sector,auth,keys,NewKeyBuf):
    global dispinf
    global EditUiEn
    HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
    sdata = bytes([eval('0x3A')])           # 3A是指令码
    sdata = sdata + bytes.fromhex(HexStr)   # 2字节机号
    sdata = sdata + bytes([1])              # 1字节扇区个数
    sdata = sdata + bytes.fromhex(CardNo)   # 4字节16进制卡号 00000000 表示可操作任意卡
    sdata = sdata + bytes([sector])         # 1字节扇区号
    sdata = sdata + bytes([auth])           # 1字节密码认证方式
    sdata = sdata +keys                     # 6字节卡密码
    sdata = sdata + NewKeyBuf               # 16字节新密码
    sdata = sdata + bytes.fromhex("55AA6699")  # 4字节防错

    s.sendto(sdata, addr)
    dispinf = 'SendTo: %s:%s' % addr + '    Data:'
    for num in range(0, len(sdata)):
        dispinf = dispinf + '%02X ' % (sdata[num])
    EditUiEn = 2
    ui.subThread.start()

if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    Frame = QtWidgets.QFrame()
    ui = Ui_Frame()
    ui.setupUi(Frame)

    screen = QDesktopWidget().screenGeometry()
    size = Frame.geometry()
    # 获得窗口相关坐标
    newLeft = (screen.width() - size.width()) // 2
    newTop = (screen.height() - size.height()) // 2
    # 移动窗口使其居中
    Frame.move(newLeft, newTop)

    Frame.show()

    ui.TEPort.setPlainText("39169")

    ui.textEdit.setPlainText("欢迎您使用我们的网络读卡器!")
    ui.textEdit_2.setPlainText("欢迎您使用我们的网络读卡器!")
    ui.textEdit_3.setPlainText("00000000")
    ui.textEdit_4.setPlainText("FFFFFFFFFFFF")
    ui.textEdit_5.setPlainText("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00")
    ui.textEdit_6.setPlainText("FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF")
    ui.textEdit_7.setPlainText('255.255.255.255:39169')
    ui.textEdit_8.setPlainText('00000')
    ui.spinBox.setValue(20)
    ui.spinBox_2.setValue(200)
    ui.spinBox_3.setValue(10)
    ui.CBauth.setCurrentIndex(1)


    addrs = socket.getaddrinfo(socket.gethostname(), None)  # 获取电脑所有网卡IP
    for item in addrs:
        if ':' not in item[4][0]:
            ui.CBIP.addItem(item[4][0])

    if ui.CBIP.count()>0:
        Bindip = ui.CBIP.currentText()
        Bindprot =int(ui.TEPort.toPlainText())

        try:
            listen = 1
            s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
            s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
            s.bind((Bindip, Bindprot))

            ui.subSockListenThread = SockListenThread()
            ui.subSockListenThread.Sock_data.connect(ui.SockGetData)
            ui.subSockListenThread.start()

            #t1=threading.Thread(target=run,args=("t1",))
            #t1.setDaemon(True)      #守护线程--也称“服务线程”,在没有用户线程可服务时会自动离开,确保关闭窗口后关闭处理线程
            #t1.start()

            ui.ListAddItem("Socket is bind to :" + Bindip + ":" + str(Bindprot))
        except:
            listen = 0
            ui.ListAddItem("Socket is bind to :" + Bindip + ":" + str(Bindprot)+" failure!" )

        changip = 1

    sys.exit(app.exec_())

猜你喜欢

转载自blog.csdn.net/zhangjin7422/article/details/127313490