草庐IT

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

津津有味道 2024-05-19 原文

 网络读卡器介绍: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_())

 

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

  1. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  2. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  3. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  4. ruby-on-rails - 如何在 Ruby on Rails 中实现由 JSF 2.0 (Primefaces) 驱动的 UI 魔法 - 2

    按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visitthehelpcenter指导。关闭10年前。问题1)我想知道ruby​​onrails是否有功能类似于primefaces的gem。我问的原因是如果您使用primefaces(http://www.primefaces.org/showcase-labs/ui/home.jsf),开发人员无需担心javascript或jquery的东西。据我所知,JSF是一个规范,基于规范的各种可用实现,prim

  5. 屏幕录制为什么没声音?检查这2项,轻松解决 - 2

    相信很多人在录制视频的时候都会遇到各种各样的问题,比如录制的视频没有声音。屏幕录制为什么没声音?今天小编就和大家分享一下如何录制音画同步视频的具体操作方法。如果你有录制的视频没有声音,你可以试试这个方法。 一、检查是否打开电脑系统声音相信很多小伙伴在录制视频后会发现录制的视频没有声音,屏幕录制为什么没声音?如果当时没有打开音频录制,则录制好的视频是没有声音的。因此,建议在录制前进行检查。屏幕上没有声音,很可能是因为你的电脑系统的声音被禁止了。您只需打开电脑系统的声音,即可录制音频和图画同步视频。操作方法:步骤1:点击电脑屏幕右下侧的“小喇叭”图案,在上方的选项中,选择“声音”。 步骤2:在“声

  6. 【高数】用拉格朗日中值定理解决极限问题 - 2

    首先回顾一下拉格朗日定理的内容:函数f(x)是在闭区间[a,b]上连续、开区间(a,b)上可导的函数,那么至少存在一个,使得:通过这个表达式我们可以知道,f(x)是函数的主体,a和b可以看作是主体函数f(x)中所取的两个值。那么可以有,  也就意味着我们可以用来替换 这种替换可以用在求某些多项式差的极限中。方法: 外层函数f(x)是一致的,并且h(x)和g(x)是等价无穷小。此时,利用拉格朗日定理,将原式替换为 ,再进行求解,往往会省去复合函数求极限的很多麻烦。使用要注意:1.要先找到主体函数f(x),即外层函数必须相同。2.f(x)找到后,复合部分是等价无穷小。3.要满足作差的形式。如果是加

  7. 深度学习部署:Windows安装pycocotools报错解决方法 - 2

    深度学习部署:Windows安装pycocotools报错解决方法1.pycocotools库的简介2.pycocotools安装的坑3.解决办法更多Ai资讯:公主号AiCharm本系列是作者在跑一些深度学习实例时,遇到的各种各样的问题及解决办法,希望能够帮助到大家。ERROR:Commanderroredoutwithexitstatus1:'D:\Anaconda3\python.exe'-u-c'importsys,setuptools,tokenize;sys.argv[0]='"'"'C:\\Users\\46653\\AppData\\Local\\Temp\\pip-instal

  8. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

  9. ruby-on-rails - Rails Associations 的更新方法是什么? - 2

    这太简单了,太荒谬了,我在任何地方都找不到关于它的任何信息,包括API文档和Rails源代码:我有一个:belongs_to关联,我开始理解当您没有关联时您在Controller中调用的正常模型方法与您有关联时调用的方法略有不同。例如,我的关联在创建Controller操作时运行良好:@user=current_user@building=Building.new(params[:building])respond_todo|format|if@user.buildings.create(params[:building])#etcetera但我找不到关于更新如何工作的文档:@user

  10. ruby - 如何更快地解决 project euler #21? - 2

    原始问题Letd(n)bedefinedasthesumofproperdivisorsofn(numberslessthannwhichdivideevenlyinton).Ifd(a)=bandd(b)=a,whereab,thenaandbareanamicablepairandeachofaandbarecalledamicablenumbers.Forexample,theproperdivisorsof220are1,2,4,5,10,11,20,22,44,55and110;therefored(220)=284.Theproperdivisorsof284are1,2,

随机推荐