Python Socket UDP通讯示例源码 多线程多窗口 界面与逻辑代码分离

读写器介绍:https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-17663462238.11.a70b5b43vR8ieG&id=17029933847icon-default.png?t=N7T8https://item.taobao.com/item.htm?spm=a1z10.5-c.w4002-17663462238.11.a70b5b43vR8ieG&id=17029933847

# pip install netifaces
import subprocess
import struct
import threading
from PyQt5.QtGui import QFont

import os
import socket
import re
import datetime
import netifaces
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt, QThread, pyqtSignal, QDateTime
from PyQt5.QtWidgets import QApplication, QWidget, QDesktopWidget, QMessageBox, QCheckBox

from SockUdpReaderPyqt5UI import Ui_Frame
from WIFISetUp import Ui_wifiwin
from NetParaSetup import Ui_NetParaWin
from ISO15693RW import Ui_ISO15693RW

import sys

Bindip = ""
Bindprot = 0
listen = 0
changip = 0
LastBuf = bytes(9)  # 保存最后接收到的信息,用于比较是否重复接收的信息
CardNuff = bytearray()  # 保存C3主动读取IC卡扇区数据


class MyDialog(QThread):  # 对话框线程
    sig = pyqtSignal(object)

    def run(self):
        self.sig.emit('')


class SockListenThread(QThread):  # Socket端口侦听线程
    Sock_data = pyqtSignal(int, str, bytes)  # 创建一个信号,将接收到的数据交给槽函数处理

    def run(self):
        global LastBuf
        global CardNuff

        while listen == 1:
            try:
                data, addr = s.recvfrom(1024)
                RemortIPort = '%s:%s' % addr
                self.Sock_data.emit(0, RemortIPort, data)
            except:
                self.Sock_data.emit(1, 'Socket端口侦听线程正在重启...', bytes(0))


# 读写15693标签
# =======================================================================================================================
class ISO15693RW(QWidget, Ui_ISO15693RW):
    iso15693Signel = pyqtSignal(str, bytes)

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton_setrwblock.clicked.connect(self.pushButton_setrwblock_clicked)
        self.pushButton_readcard.clicked.connect(self.pushButton_readcard_clicked)
        self.pushButton_writecard.clicked.connect(self.pushButton_writecard_clicked)
        mainWindow.rw15693Signel.connect(self.getrw15693inf)

    def open(self):
        self.show()

    def closeEvent(self, event):
        mainWindow.setEnabled(True)

    def getrw15693inf(self, code, remoiport,dispinf): #接收到主窗口更新显示的信号
        if (remoiport==self.lineEdit_RemoIPort.text().strip()):
            if (code == 1):
                self.lineEdit_RWCardno.setText(dispinf)
            elif (code == 2):
                self.plainTextEdit_Data.setPlainText(dispinf)
            elif (code == 3):
                self.lineEdit_disp.setText(dispinf)

    def pushButton_setrwblock_clicked(self):  # 设置15693网络读写器 主动读卡块号,未选择块号则读取UID卡号上传
        self.lineEdit_disp.setText('')
        RemoIPort = self.lineEdit_RemoIPort.text().strip()
        if (IsIport(RemoIPort) == False):
            QMessageBox.critical(self, "警告", "远程设备IP端口输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIPort.setFocus()
            return

        afi = self.spinBox_AFI.value()
        masklen = self.spinBox_masklen.value()
        cardmask = self.lineEdit_Mask.text().strip()
        try:
            maskbuf = bytes.fromhex(cardmask)
            if (len(maskbuf) != 8):
                QMessageBox.critical(self, "警告", "掩码必须是16位16进制数!", QMessageBox.Yes)
                self.lineEdit_Mask.setFocus()
                return
        except:
            QMessageBox.critical(self, "警告", "掩码必须是16位16进制数!", QMessageBox.Yes)
            self.lineEdit_Mask.setFocus()
            return

        blocks = 255  # 块数取255,表示每次更新所有参数区

        sendbuf = bytes([eval('0x47')])  # 1字节指令码
        sendbuf = sendbuf + bytes.fromhex('0000')  # 2字节机号 0000表示任意机
        sendbuf = sendbuf + bytes([masklen])  # 1字节掩码长度
        sendbuf = sendbuf + bytes.fromhex(cardmask)  # 8字节掩码
        sendbuf = sendbuf + bytes([afi])  # 1字节AFI
        sendbuf = sendbuf + bytes([blocks % 256]) + bytes([blocks // 256])  # 2字节的块数

        seleblock = ''
        j = 0
        for i in range(64):
            self.chckbox = self.findChild(QCheckBox, "checkBox%d" % (i))
            if self.chckbox.isChecked():
                seleblock = '1' + seleblock
            else:
                seleblock = '0' + seleblock
            if (len(seleblock) == 8):
                sendbuf = sendbuf + bytes([int(seleblock, 2)])
                seleblock = ''
                j = j + 1

        for i in range(j, 32):
            sendbuf = sendbuf + bytes([0])

        sendbuf = sendbuf + bytes.fromhex('55AA6699')
        self.iso15693Signel.emit(RemoIPort, sendbuf)

    def pushButton_readcard_clicked(self):      #发指令驱动15693读写器读指定块号数据
        self.lineEdit_disp.setText('')
        self.plainTextEdit_Data.setPlainText('')

        RemoIPort = self.lineEdit_RemoIPort.text().strip()
        if (IsIport(RemoIPort) == False):
            QMessageBox.critical(self, "警告", "远程设备IP端口输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIPort.setFocus()
            return

        sendbuf = bytes([eval('0x30')])  # 1字节指令码
        sendbuf = sendbuf + bytes.fromhex('0000')  # 2字节机号 0000表示任意机

        if (self.radioButton_thiscard.isChecked()):  # 读写指定卡号的卡片
            RWCardNo = self.lineEdit_RWCardno.text().strip()
            try:
                rwcardbuf = bytes.fromhex(RWCardNo)
                if (len(rwcardbuf) != 8):
                    QMessageBox.critical(self, "警告", "读写卡号必须是16位16进制数!", QMessageBox.Yes)
                    self.lineEdit_RWCardno.setFocus()
                    return
                else:
                    sendbuf = sendbuf + bytes([64]) + rwcardbuf[::-1]  # 注意传入的卡号高位在前
            except:
                QMessageBox.critical(self, "警告", "读写卡号必须是16位16进制数!", QMessageBox.Yes)
                self.lineEdit_RWCardno.setFocus()
                return
        else:  # 读写感应区上任意卡
            sendbuf = sendbuf + bytes([0]) + bytes.fromhex('0000000000000000')

        afi = self.spinBox_AFI.value()
        sendbuf = sendbuf + bytes([afi])  # 指定AFI

        seleblock = ''
        blockflaglen = 0
        blockflag = bytes()
        for i in range(64):
            self.chckbox = self.findChild(QCheckBox, "checkBox%d" % (i))
            if self.chckbox.isChecked():
                seleblock = '1' + seleblock
                blockflaglen = i + 1
            else:
                seleblock = '0' + seleblock

            if (len(seleblock) == 8):
                blockflag = blockflag + bytes([int(seleblock, 2)])
                seleblock = ''

        sendbuf = sendbuf + bytes([blockflaglen % 256]) + bytes([blockflaglen // 256])  # 2字节的块数

        j = (blockflaglen + 7) // 8
        sendbuf = sendbuf + blockflag[0:j]

        sendbuf = sendbuf + bytes.fromhex('55AA6699')
        self.iso15693Signel.emit(RemoIPort, sendbuf)

    def pushButton_writecard_clicked(self):     #发指令驱动15693读写器写数据到指定块内
        self.lineEdit_disp.setText('')
        writestr=self.plainTextEdit_Data.toPlainText().strip()
        if (writestr==''):
            writestr='块号:00 数据:01020304\n'
            writestr =writestr+ '块号:01 数据:05060708\n'
            self.plainTextEdit_Data.setPlainText(writestr)
            QMessageBox.critical(self, "警告", "请按此格式输入要写入的数据!", QMessageBox.Yes)

        j=0
        k=4     #一般NXP每块都是 4 个字节
        datainfostr=""
        writearray = writestr.split('\n')
        for i in range(0,len(writearray)):
            if (len(writearray[i])>0):
                blockinfostr=writearray[i].split(":")
                if (len(blockinfostr)>=2):
                    block='%02X' % (int(blockinfostr[1][0:2]))
                    writedata=blockinfostr[2].strip()
                    if (i==0 and  len(writedata)==16):
                        k=8 #本次写入的是每块有 8 个字节的卡片,如富士通的MB89R118

                    if (len(writedata)==k*2):
                        datainfostr=datainfostr+block+writedata
                        j=j+1
                    else:
                        QMessageBox.critical(self, "警告", "第 "+block+" 块的数据不正确!", QMessageBox.Yes)
                        return

                    if (k==4 and j==20):
                        QMessageBox.information(self, "警告", "每块4字节的卡片,一次最多写20块,多于20块请分次写入!", QMessageBox.Yes)
                        break

                    if (k==8 and j==10):
                        QMessageBox.information(self, "警告", "每块8字节的卡片,一次最多写10块,多于10块请分次写入!", QMessageBox.Yes)
                        break

        if (j==0):
            QMessageBox.critical(self, "警告", "请按样本输入正确的写卡数据!", QMessageBox.Yes)
            return

        RemoIPort = self.lineEdit_RemoIPort.text().strip()
        if (IsIport(RemoIPort) == False):
            QMessageBox.critical(self, "警告", "远程设备IP端口输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIPort.setFocus()
            return

        sendbuf = bytes([eval('0x31')])  # 1字节指令码
        sendbuf = sendbuf + bytes.fromhex('0000')  # 2字节机号 0000表示任意机

        if (self.radioButton_thiscard.isChecked()):  # 读写指定卡号的卡片
            RWCardNo = self.lineEdit_RWCardno.text().strip()
            try:
                rwcardbuf = bytes.fromhex(RWCardNo)
                if (len(rwcardbuf) != 8):
                    QMessageBox.critical(self, "警告", "读写卡号必须是16位16进制数!", QMessageBox.Yes)
                    self.lineEdit_RWCardno.setFocus()
                    return
                else:
                    sendbuf = sendbuf + bytes([64]) + rwcardbuf[::-1]  # 注意传入的卡号高位在前
            except:
                QMessageBox.critical(self, "警告", "读写卡号必须是16位16进制数!", QMessageBox.Yes)
                self.lineEdit_RWCardno.setFocus()
                return
        else:  # 读写感应区上任意卡
            sendbuf = sendbuf + bytes([0]) + bytes.fromhex('0000000000000000')

        afi = self.spinBox_AFI.value()
        sendbuf = sendbuf + bytes([afi])  # 指定AFI
        sendbuf = sendbuf + bytes([k])    # 每块字节数,15693卡每块的字节数,大多卡为每块4个字节,富士通15693卡有一些型号是8个字节
        sendbuf = sendbuf + bytes([j])    # 本次总计写块数,如果每块4字节 一次最多可写20块, 每块8字节一次最多写10块
        sendbuf = sendbuf + bytes.fromhex(datainfostr)  # 本次写入的每块数
        sendbuf = sendbuf + bytes.fromhex('55AA6699')   #  固定的后缀
        self.iso15693Signel.emit(RemoIPort, sendbuf)

# 设置读卡器网络参数=========================================================================================================
class NetParaSetwindow(QWidget, Ui_NetParaWin):
    netparaSignel = pyqtSignal(str, bytes)

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.pushButton_computerIP.clicked.connect(self.pushButton_computerIP_clicked)
        self.pushButton_broadcast.clicked.connect(self.pushButton_broadcast_clicked)
        self.pushButton_computerMAC.clicked.connect(self.pushButton_computerMAC_clicked)
        self.pushButton_gateway.clicked.connect(self.pushButton_gateway_clicked)
        self.pushButton_gatewayMAC.clicked.connect(self.pushButton_gatewayMAC_clicked)
        self.pushButton_SetupNew.clicked.connect(self.pushButton_SetupNew_clicked)
        self.pushButton_SetupOld.clicked.connect(self.pushButton_SetupOld_clicked)
        self.radioButton_RemoMACAuto.toggled.connect(self.radioButton_RemoMACAuto_changeEvent)
        self.radioButton_Gatwayauto.toggled.connect(self.radioButton_Gatwayauto_changeEvent)
        self.pushButton_SetTCP.clicked.connect(self.pushButton_SetTCP_clicked)
        self.pushButton_SetHttp.clicked.connect(self.pushButton_SetHttp_clicked)

    def open(self):
        self.show()

    def closeEvent(self, event):
        mainWindow.setEnabled(True)

    def pushButton_computerIP_clicked(self):
        self.lineEdit_RemoIP.setText(mainWindow.CBIP.currentText().strip())
        self.lineEdit_RemoMAC.setText(get_mac_address(mainWindow.CBIP.currentText().strip()))

    def pushButton_broadcast_clicked(self):
        self.lineEdit_RemoIP.setText("255.255.255.255")
        self.lineEdit_RemoMAC.setText("FF-FF-FF-FF-FF-FF")
        self.radioButton_RemoMACAuto.setChecked(True)
        return

    def pushButton_computerMAC_clicked(self):
        self.lineEdit_RemoMAC.setText(get_mac_address(self.lineEdit_RemoIP.text()))

    def pushButton_gateway_clicked(self):
        self.lineEdit_Gatwag.setText(get_default_gateway())
        self.lineEdit_GatwayMAC.setText(get_mac_address(self.lineEdit_Gatwag.text()))

    def pushButton_gatewayMAC_clicked(self):
        self.lineEdit_GatwayMAC.setText(get_mac_address(self.lineEdit_Gatwag.text()))

    def radioButton_RemoMACAuto_changeEvent(self):
        if (self.radioButton_RemoMACAuto.isChecked()):
            self.lineEdit_RemoMAC.setText("FF-FF-FF-FF-FF-FF")

    def radioButton_Gatwayauto_changeEvent(self):
        if (self.radioButton_Gatwayauto.isChecked()):
            self.lineEdit_GatwayMAC.setText("FF-FF-FF-FF-FF-FF")

    def pushButton_SetupOld_clicked(self):  # 固件日期为2015年以前设备的网络参数设置
        self.plainTextEdit_Disp.setPlainText(" ")

        DevNo = int(self.lineEdit_ReaderNnm.text())
        DEvIp = self.lineEdit_ReaderIP.text()
        DevMask = self.lineEdit_ReaderMask.text()
        ServeIp = self.lineEdit_RemoIP.text()
        SerialNum = self.lineEdit_Serial.text()

        sdata = bytes([eval('0xF0')])  # 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:
            QMessageBox.critical(self, "警告", "设备IP地址输入错误!", QMessageBox.Yes)
            self.lineEdit_ReaderIP.setFocus()
            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:
            QMessageBox.critical(self, "警告", "设备子网掩码输入错误!", QMessageBox.Yes)
            self.lineEdit_ReaderMask.setFocus()
            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:
            QMessageBox.critical(self, "警告", "设备远程服务器IP输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIP.setFocus()
            return

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

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

        sdata = sdata + bytes([self.comboBox_beep.currentIndex()])
        if (self.checkBox.isChecked()):
            RemoIPort = "255.255.255.255:39169"
        else:
            RemoIPort = self.lineEdit_RemoIPort.text().strip()
            if (IsIport(RemoIPort) == False):
                QMessageBox.critical(self, "警告", "远程设备IP端口输入错误!", QMessageBox.Yes)
                self.lineEdit_RemoIPort.setFocus()
                return
        self.netparaSignel.emit(RemoIPort, sdata)

    def pushButton_SetupNew_clicked(self):  # 固件日期为2015年以后设备的网络参数设置
        self.plainTextEdit_Disp.setPlainText(" ")
        if (self.radioButton_RemoMACAuto.isChecked()):
            self.lineEdit_RemoMAC.setText("FF-FF-FF-FF-FF-FF")

        if (self.radioButton_Gatwayauto.isChecked()):
            self.lineEdit_GatwayMAC.setText("FF-FF-FF-FF-FF-FF")

        DevNo = int(self.lineEdit_ReaderNnm.text())
        DEvIp = self.lineEdit_ReaderIP.text()
        DevMask = self.lineEdit_ReaderMask.text()
        DevPort = int(self.lineEdit_ReaderPort.text())
        DevGetway = self.lineEdit_Gatwag.text()
        GetwayMac = self.lineEdit_GatwayMAC.text()
        ServeIp = self.lineEdit_RemoIP.text()
        ServerMac = self.lineEdit_RemoMAC.text()
        SerialNum = self.lineEdit_Serial.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:
            QMessageBox.critical(self, "警告", "设备IP地址输入错误!", QMessageBox.Yes)
            self.lineEdit_ReaderIP.setFocus()
            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:
            QMessageBox.critical(self, "警告", "设备子网掩码输入错误!", QMessageBox.Yes)
            self.lineEdit_ReaderMask.setFocus()
            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:
            QMessageBox.critical(self, "警告", "设备远程服务器IP输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIP.setFocus()
            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:
            QMessageBox.critical(self, "警告", "设备远程服务器MAC输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoMAC.setFocus()
            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:
            QMessageBox.critical(self, "警告", "设备网关IP输入错误!", QMessageBox.Yes)
            self.lineEdit_Gatwag.setFocus()
            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:
            QMessageBox.critical(self, "警告", "设备网关MAC输入错误!", QMessageBox.Yes)
            self.lineEdit_GatwayMAC.setFocus()
            return

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

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

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

        searchcode = self.comboBox_beep.currentIndex()
        if (self.radioButton_RemoMACAuto.isChecked()):
            searchcode = searchcode + 2
        if (self.radioButton_Gatwayauto.isChecked()):
            searchcode = searchcode + 4
        if (self.checkBox_DHCP.isChecked()):
            searchcode = searchcode + 8
        if (self.comboBox_SendEn.currentIndex() == 1):
            searchcode = searchcode + 16
        searchcode = searchcode + self.comboBox_Sendinterval.currentIndex() * 32
        sdata = sdata + bytes([searchcode])

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

        if (self.checkBox.isChecked()):
            RemoIPort = "255.255.255.255:39169"
        else:
            RemoIPort = self.lineEdit_RemoIPort.text().strip()
            if (IsIport(RemoIPort) == False):
                QMessageBox.critical(self, "警告", "远程设备IP端口输入错误!", QMessageBox.Yes)
                self.lineEdit_RemoIPort.setFocus()
                return
        self.netparaSignel.emit(RemoIPort, sdata)

    def pushButton_SetTCP_clicked(self):  # 设置TCP协议读卡器 远程服务器侦听端口
        self.plainTextEdit_Disp.setPlainText('')

        RemoIPort = self.lineEdit_RemoIPort.text().strip()
        if (IsIport(RemoIPort) == False):
            QMessageBox.critical(self, "警告", "远程设备IP端口输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIPort.setFocus()
            return

        sdata = bytes([eval('0x1D')])  # 1字节指令码
        sdata = sdata + bytes.fromhex("0000075C04")

        DevPort = int(self.lineEdit_ReaderPort.text())
        try:
            HexStr = '%02X%02X' % (DevPort % 256, DevPort // 256)  # 2字节端口号
            sdata = sdata + bytes.fromhex(HexStr)
        except:
            QMessageBox.critical(self, "警告", "读卡器通讯端口输入错误!", QMessageBox.Yes)
            self.lineEdit_ReaderPort.setFocus()
            return

        DevPort = int(self.lineEdit_TCPRemoPort.text())
        try:
            HexStr = '%02X%02X' % (DevPort % 256, DevPort // 256)  # 2字节端口号
            sdata = sdata + bytes.fromhex(HexStr)
        except:
            QMessageBox.critical(self, "警告", "服务器TCP通讯端口输入错误!", QMessageBox.Yes)
            self.lineEdit_TCPRemoPort.setFocus()
            return
        sdata = sdata + bytes([sdata[6] ^ sdata[7] ^ sdata[8] ^ sdata[9]])
        sdata = sdata + bytes.fromhex("55AA6699")
        self.netparaSignel.emit(RemoIPort, sdata)

    def pushButton_SetHttp_clicked(self):  # 设置HTTP协议读卡器数据传送方式、服务端侦听端口 及 访问文件
        self.plainTextEdit_Disp.setPlainText('')

        RemoIPort = self.lineEdit_RemoIPort.text().strip()
        if (IsIport(RemoIPort) == False):
            QMessageBox.critical(self, "警告", "远程设备IP端口输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIPort.setFocus()
            return

        filename = self.lineEdit_filename.text().strip()
        filenamebuf = bytes(filename, encoding='gbk')
        filelen = len(filenamebuf)
        if (filelen == 0 or filelen > 252):
            QMessageBox.critical(self, "警告", "访问文件不可以为空,文件长度也不可以>252!", QMessageBox.Yes)
            self.lineEdit_filename.setFocus()
            return
        if (filename[0:1] == '/'):
            QMessageBox.critical(self, "警告", "访问文件首字符不可以为: /", QMessageBox.Yes)
            self.lineEdit_filename.setFocus()
            return
        if (filename[0:4] == 'http'):
            QMessageBox.critical(self, "警告", "访问文件无需带域名!", QMessageBox.Yes)
            self.lineEdit_filename.setFocus()
            return

        DevPort = int(self.lineEdit_HttpRemoPort.text())
        try:
            HexStr = '%02X%02X' % (DevPort % 256, DevPort // 256)  # 2字节端口号
            PortBuf = bytes.fromhex(HexStr)
        except:
            QMessageBox.critical(self, "警告", "读卡器通讯端口输入错误!", QMessageBox.Yes)
            self.lineEdit_ReaderPort.setFocus()
            return

        sdata = bytes([eval('0x1D')])  # 1字节指令码
        sdata = sdata + bytes.fromhex("0000")  # 2字节机号 00表示任意机号
        sdata = sdata + bytes([filelen + 7])
        sdata = sdata + bytes([91])  # 设定HTTP协议的文件路径、上传方式  标识
        sdata = sdata + bytes([filelen + 4])
        sdata = sdata + bytes([self.comboBox_Sendmodel.currentIndex()])  # 提交方式
        sdata = sdata + bytes([255])
        sdata = sdata + PortBuf  # 服务器侦听端口
        sdata = sdata + filenamebuf  # 访问文件

        crc = sdata[6] ^ sdata[7] ^ sdata[8] ^ sdata[9]
        for num in range(0, len(filenamebuf)):
            crc = crc ^ filenamebuf[num]

        sdata = sdata + bytes([crc])
        sdata = sdata + bytes.fromhex("55AA6699")

        self.netparaSignel.emit(RemoIPort, sdata)


# 设置读卡器WIFI热点========================================================================================================
class WifiSetWindow(QWidget, Ui_wifiwin):
    WifiSignel = pyqtSignal(int, str, bytes)  # 创建一个信号,向主窗口请求发送对应的指令

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("WIFI热点参数设置")
        self.radioButton_DHCP.toggled.connect(self.radioButton_DHCP_changeEvent)
        self.pushButton_SetUp.clicked.connect(self.pushButton_SetUp_click)
        self.pushButton_Read.clicked.connect(self.pushButton_Read_click)

    def open(self):
        self.show()

    def closeEvent(self, event):
        mainWindow.setEnabled(True)

    def radioButton_DHCP_changeEvent(self):
        if (self.radioButton_DHCP.isChecked()):
            self.groupBox.setVisible(False)
        else:
            self.groupBox.setVisible(True)

    def pushButton_SetUp_click(self):  # 设置WIFI热点名称、密码、WIFIIP及数据传送方式
        self.plainTextEdit.setPlainText(" ")
        RemoIPort = self.lineEdit_RemoIPort.text().strip()
        if (IsIport(RemoIPort) == False):
            QMessageBox.critical(self, "警告", "设备有线IP端口输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIPort.setFocus()
            return

        wifiname = bytes(self.lineEdit_SSID.text().strip(), encoding='utf8')
        namelen = len(wifiname)
        if (namelen > 60):
            self.plainTextEdit.setPlainText("热点名称长度不可以大于60字节!")
            return
        wifipass = bytes(self.lineEdit_Password.text().strip(), encoding='utf8')
        passlen = len(wifipass)
        if (passlen > 64):
            self.plainTextEdit.setPlainText("WIFI密钥长度不可以大于64字节!")
            return

        comb = bytes([eval('0xF7')])  # F7是指令码
        comb = comb + bytes.fromhex('0000')  # 2字节机号
        comb = comb + bytes([namelen])  # 1字节热点名称长度
        if self.checkBox.isChecked():
            comb = comb + bytes([passlen])  # 1字节密码长度
        else:
            comb = comb + bytes([0])  # 1字节密码长度
        comb = comb + wifiname  # 热点名称
        for num in range(namelen, 60):  # 热点名称长度不足60,占位符
            comb = comb + bytes([0])

        comb = comb + wifipass  # WiFI密码
        for num in range(passlen, 64):  # WiFI密码长度不足64,占位符
            comb = comb + bytes([0])

        if (self.radioButton_DHCP.isChecked()):  # wifi的IP是DHCP自动分配
            comb = comb + bytes([0])
            comb = comb + bytes.fromhex('000000000000000000000000')
        else:  # wifi的IP是静态绑定
            wifiip = GetHexIPAdd(self.lineEdit_IP.text())
            if (wifiip == '00000000'):
                self.plainTextEdit.setPlainText("WIFI的IP地址输入错误!")
                self.lineEdit_IP.setFocus()
                return

            wifimask = GetHexIPAdd(self.lineEdit_mask.text())
            if (wifiip == '00000000'):
                self.plainTextEdit.setPlainText("WIFI的掩码地址输入错误!")
                self.lineEdit_mask.setFocus()
                return

            wifigetway = GetHexIPAdd(self.lineEdit_gateway.text())
            if (wifiip == '00000000'):
                self.plainTextEdit.setPlainText("WIFI的掩码地址输入错误!")
                self.lineEdit_gateway.setFocus()
                return
            comb = comb + bytes([1])
            comb = comb + bytes.fromhex(wifiip)
            comb = comb + bytes.fromhex(wifimask)
            comb = comb + bytes.fromhex(wifigetway)

        comb = comb + bytes([self.comboBox_Sendmode.currentIndex()])
        comb = comb + bytes.fromhex('55AA6699')  # 指令结束码,抗网络上的干扰信号

        self.WifiSignel.emit(1, RemoIPort, comb)  # 发送信号,主窗口接收到信号后,触发主窗口槽函数发送指令

    def pushButton_Read_click(self):  # 查询WIFI连接状态
        self.plainTextEdit.setPlainText(" ")
        RemoIPort = self.lineEdit_RemoIPort.text().strip()
        if (IsIport(RemoIPort) == False):
            QMessageBox.critical(self, "警告", "设备有线IP端口输入错误!", QMessageBox.Yes)
            self.lineEdit_RemoIPort.setFocus()
            return

        comb = bytes.fromhex("A40000")
        global LastBuf
        LastBuf = bytes(9)
        self.WifiSignel.emit(1, RemoIPort, comb)  # 发送信号,主窗口接收到信号后,触发主窗口槽函数发送指令


# 主窗口,侦听网络端口获取刷卡信息、向读卡器发送显示、响声、语音=====================================================================
class MainWindow(QtWidgets.QMainWindow, Ui_Frame):
    rw15693Signel = pyqtSignal(int, str,str)

    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        self.setupUi(self)

        self.PBSearch.clicked.connect(self.PBSearch_click)
        self.PBClear.clicked.connect(self.PBClear_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)
        self.PBSetRW.clicked.connect(self.PBSetRW_click)
        self.PBWifiSet.clicked.connect(self.PBWifiSet_click)
        self.PBGetmodel.clicked.connect(self.PBGetmodel_click)
        self.PB15693RW.clicked.connect(self.PB15693RW_click)

    def Getiso15693Signal(self, remortiport, sdata):
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        s.sendto(sdata, (Remoip, Reprot))  # 发送设置WIFI参数的指令
        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    def GetWiFiWindoSignal(self, sigcode, remortiport, sdata):
        if (sigcode == 1):  # 设置WIFI叁数的信号
            FieldsList = remortiport.split(':')
            Remoip = FieldsList[0]
            Reprot = int(FieldsList[1])

            s.sendto(sdata, (Remoip, Reprot))  # 发送设置WIFI参数的指令

            SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[
                                               0:22] + ' Data:'  # 为方便开发,打印出详细的指令
            for num in range(0, len(sdata)):
                SendInf = SendInf + '%02X ' % (sdata[num])
            self.ListAddItem(SendInf)

    def GetNetParaSetSignal(self, remortiport, sdata):
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])

        s.sendto(sdata, (Remoip, Reprot))  # 发送设置WIFI参数的指令

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    def SockGetData(self, dispcode, RemortIPort, data):
        global LastBuf
        global CardNuff

        if (dispcode == 0):
            self.textEdit_7.setText(RemortIPort)
            DispStr = get_time() + 'FromIP:' + (RemortIPort + '                      ')[0:22] + ' Data:'
            for num in range(0, len(data)):
                DispStr = DispStr + '%02X ' % (data[num])
            self.ListAddItem(DispStr)

        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]):  # 比较是否是重发数据
                exit  # 是设备重发的数据,直接丢弃不做处理
            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 = '%02X' % (data[33])
                    Beep = ('00000000' + bin(data[34])[2:])[-8:]

                    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

                    rowPosition = self.tableWidget.rowCount()
                    self.tableWidget.insertRow(rowPosition)
                    NewItem = QtWidgets.QTableWidgetItem(DevNo)
                    self.tableWidget.setItem(rowPosition, 0, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(DEvIp)
                    self.tableWidget.setItem(rowPosition, 1, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(DevMask)
                    self.tableWidget.setItem(rowPosition, 2, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(DevPort)
                    self.tableWidget.setItem(rowPosition, 3, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(DevGetway)
                    self.tableWidget.setItem(rowPosition, 4, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(GetwayMac)
                    self.tableWidget.setItem(rowPosition, 5, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(ServeIp)
                    self.tableWidget.setItem(rowPosition, 6, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(ServerMac)
                    self.tableWidget.setItem(rowPosition, 7, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(Search)
                    self.tableWidget.setItem(rowPosition, 8, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(Beep)
                    self.tableWidget.setItem(rowPosition, 9, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(DevMac[6:17])
                    self.tableWidget.setItem(rowPosition, 10, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(DevMac)
                    self.tableWidget.setItem(rowPosition, 11, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(SerialNum)
                    self.tableWidget.setItem(rowPosition, 12, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem(HCMac)
                    self.tableWidget.setItem(rowPosition, 13, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem('                     ')
                    self.tableWidget.setItem(rowPosition, 14, NewItem)
                    NewItem = QtWidgets.QTableWidgetItem('            ')
                    self.tableWidget.setItem(rowPosition, 15, NewItem)
                    self.tableWidget.resizeColumnsToContents()

                    self.textEdit_8.setText(DevNo)
                    dispinf = '数据解析:设备响应搜索指令、开机标识:F2,设备信息已在表格内显示,如需修改设备网络参数,先在表格内点击要修改的设备再点击 "修改选定设备的网络参数" 键!'
                    self.textEdit_9.setText(dispinf)

                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卡信息的数据包,对信息解析
                    self.DisableSendAge(RemortIPort, data)

                    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.textEdit_9.setText(dispinf)
                    self.textEdit_8.setPlainText(DevNo)
                    self.textEdit_3.setText(Card16H)
                    self.PBSendDispBeep_click()

                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.textEdit_9.setText(dispinf)

                        m = data[9] * 48
                        CardInfStr = ''
                        for num in range(0, m):
                            CardInfStr = CardInfStr + '%02X ' % (CardNuff[num])
                        self.textEdit_5.setPlainText(CardInfStr)

                        CardNuff = bytearray()  # 已接收完,清空接收缓冲
                        self.textEdit_3.setText(Card16H)

                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.textEdit_9.setText(dispinf)
                        self.textEdit_8.setText(DevNo)
                        self.textEdit_3.setText(Card16H)
                        self.textEdit_5.setPlainText(CardInfStr)
                    else:
                        if (data[13] == 12):
                            dispinf = dispinf + ",卡密码认证失败!本次读卡失败!"
                            self.textEdit_9.setText(dispinf)
                        else:
                            dispinf = dispinf + ",读卡失败,错误代码:%02X" % (data[13])
                            self.textEdit_9.setText(dispinf)

                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.textEdit_9.setText(dispinf)

                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.textEdit_9.setText(dispinf)
                    self.textEdit_8.setText(DevNo)

                elif (data[0] == eval('0xA4')):  # 返回WIFI连接状态
                    dispinf = 'WIFI的IP地址:%d.%d.%d.%d' % (data[7], data[8], data[9], data[10]) + "\n"
                    dispinf = dispinf + 'WIFI子网掩码:%d.%d.%d.%d' % (data[11], data[12], data[13], data[14]) + "\n"
                    dispinf = dispinf + '本地 MAC地址:%02X-%02X-%02X-%02X-%02X-%02X' % (
                    data[15], data[16], data[17], data[18], data[19], data[20]) + "\n"
                    dispinf = dispinf + '  WIFI网关IP:%d.%d.%d.%d' % (data[21], data[22], data[23], data[24]) + "\n"
                    dispinf = dispinf + '网关 MAC地址:%02X-%02X-%02X-%02X-%02X-%02X' % (
                    data[25], data[26], data[27], data[28], data[29], data[30]) + "\n"
                    if (data[31] == 0):
                        dispinf = dispinf + 'WIFI网络状态:已连接wifi' + '\n'
                    elif (data[31] == 1):
                        dispinf = dispinf + 'WIFI网络状态:连接失败!' + '\n'
                    elif (data[31] == 2):
                        dispinf = dispinf + 'WIFI网络状态:已初始化!' + '\n'
                    else:
                        dispinf = dispinf + 'WIFI网络状态:未初始化!' + '\n'
                    dispinf = dispinf + '读卡器  名称:' + data[34:(34 + data[32])].decode('utf-8') + '\n'
                    dispinf = dispinf + 'WIFI热点名称:' + data[44:(44 + data[33])].decode('utf-8') + '\n'

                    self.wifiset.plainTextEdit.setPlainText(dispinf)

                elif (data[0] == eval('0xF6')):  # 返回设备版本型号、固件日期
                    DEvIp = '%d.%d.%d.%d' % (data[1], data[2], data[3], data[4])  # 设备IP
                    DevNo = '%05d' % (data[5] + data[6] * 256)  # 机号
                    namelen = data[7]
                    namebufbeg = 8
                    namebufend = namebufbeg + namelen
                    namestr = data[namebufbeg:namebufend].decode('gbk')

                    verlen = data[namebufend]
                    verbufbeg = namebufend + 1
                    verbufend = verbufbeg + verlen
                    verstr = '' + data[verbufbeg:verbufend].decode('gbk') + ''

                    SerialNum = ''
                    if (data[verbufend] == eval('0xFF')):
                        for num in range(verbufend + 1, len(data)):
                            SerialNum = SerialNum + '%02X' % (data[num])

                    rows = self.tableWidget.rowCount()
                    if (rows > 0):
                        for num in range(0, rows):
                            if (DEvIp == self.tableWidget.item(num, 1).text() and SerialNum == self.tableWidget.item(
                                    num, 12).text()):
                                self.tableWidget.item(num, 14).setText(namestr)
                                self.tableWidget.item(num, 15).setText(verstr)
                                break
                elif (data[0] == eval('0x47')):  # 设置15693读写器读卡块号成功
                    self.rw15693Signel.emit(3,RemortIPort, "设置15693读写器主动读卡块号成功!")

                elif (data[0] == eval('0xC7')):  # 15693卡刷卡信息
                    self.DisableSendAge(RemortIPort, data)

                    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)  # 数据包序号
                    if (data[9] == eval('0x00')):
                        self.rw15693Signel.emit(3, RemortIPort, "卡不在感应区!")
                    else:
                        Card16H = '%02X%02X%02X%02X%02X%02X%02X%02X' % (
                        data[19], data[18], data[17], data[16], data[15], data[14], data[13], data[12])  # 原始16进制卡号
                        self.rw15693Signel.emit(1,RemortIPort, Card16H)
                        if (self.findChild(QWidget, "ISO15693标签读写器测试")):
                            self.ISO15693RW.lineEdit_RWCardno.setText(Card16H)
                        if (data[9] == eval('0x01')):  # 主动读取15693卡号
                            SerialNum = ''  # 设备硬件序列号
                            for num in range(20, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            dispinf = '数据解析:主动读取15693卡号,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H + ",硬件序列号:" + SerialNum
                            self.rw15693Signel.emit(3, RemortIPort, "主动读取15693卡号成功!")
                        elif (data[9] == eval('0x02')):  # 主动读取15693卡号、块数据
                            DSFID = '%02X' % (data[11])
                            blockdata = ''
                            for j in range(1, data[21] + 1):
                                blockdata = blockdata + '块号:%02d' % (data[(j - 1) * (data[20] + 1) + 22]) + ' 数据:'
                                for i in range(1, data[20] + 1):
                                    blockdata = blockdata + '%02X' % (data[(j - 1) * (data[20] + 1) + 22 + i])
                                blockdata = blockdata + "\n"

                            SerialNum = ''  # 设备硬件序列号
                            for num in range(len(data) - 8, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            dispinf = '数据解析:主动读取15693卡号及块数据,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H + ',DSFID:' + DSFID + ",硬件序列号:" + SerialNum
                            self.rw15693Signel.emit(2,RemortIPort, blockdata)
                            self.rw15693Signel.emit(3, RemortIPort, "主动读取15693卡号及块数据成功!")
                        elif (data[9] == eval('0x03')):  # 电脑发指令读卡成功,仅返回卡号
                            SerialNum = ''  # 设备硬件序列号
                            for num in range(20, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            dispinf = '数据解析:接收指令读取15693卡号,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H + ",硬件序列号:" + SerialNum
                            self.rw15693Signel.emit(3, RemortIPort, "接收指令读取15693卡号成功!")
                        elif (data[9] == eval('0x04')):  # 电脑发指令读卡成功
                            DSFID = '%02X' % (data[11])
                            blockdata = ''
                            for j in range(1, data[21] + 1):
                                blockdata = blockdata + '块号:%02d' % (data[(j - 1) * (data[20] + 1) + 22]) + ' 数据:'
                                for i in range(1, data[20] + 1):
                                    blockdata = blockdata + '%02X' % (data[(j - 1) * (data[20] + 1) + 22 + i])
                                blockdata = blockdata + "\n"

                            SerialNum = ''  # 设备硬件序列号
                            for num in range(len(data) - 8, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            dispinf = '数据解析:接收指令读取15693卡号及块数据,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H + ',DSFID:' + DSFID + ",硬件序列号:" + SerialNum
                            self.rw15693Signel.emit(2,RemortIPort, blockdata)
                            self.rw15693Signel.emit(3, RemortIPort, "接收指令读取15693卡号及块数据成功!")
                        elif (data[9] == eval('0x05')):  # 电脑发指令读卡成功,仅返回卡号
                            DSFID = '%02X' % (data[11])
                            SerialNum = ''  # 设备硬件序列号
                            for num in range(20, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            dispinf = '数据解析:电脑发指令重新读卡号成功,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H+ ',DSFID:' + DSFID + ",硬件序列号:" + SerialNum
                            self.rw15693Signel.emit(3, RemortIPort, "接收指令重新读卡号成功成功!")
                        elif (data[9] == eval('0x06')):  # 电脑发指令写卡成功
                            DSFID = '%02X' % (data[11])
                            SerialNum = ''  # 设备硬件序列号
                            for num in range(20, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            dispinf = '数据解析:电脑发指令写卡成功,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H+ ',DSFID:' + DSFID + ",硬件序列号:" + SerialNum
                            self.rw15693Signel.emit(3, RemortIPort, "电脑发指令写卡成功!")
                        elif (data[9] == eval('0x07')):  # 卡离开感应区
                            DSFID = '%02X' % (data[11])
                            SerialNum = ''  # 设备硬件序列号
                            for num in range(20, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            dispinf = '数据解析:卡离开感应区,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H+ ',DSFID:' + DSFID + ",硬件序列号:" + SerialNum
                            self.rw15693Signel.emit(3, RemortIPort, "卡离开感应区!")
                        elif (data[9] == eval('0x6A')):  # 电脑发指令写卡失败,返回卡号
                            DSFID = '%02X' % (data[11])
                            SerialNum = ''  # 设备硬件序列号
                            for num in range(20, len(data)):
                                SerialNum = SerialNum + '%02X' % (data[num])
                            dispinf = '数据解析:电脑发指令写卡失败,设备IP:' + DEvIp + ',机号:' + DevNo + ",数据包号:" + FrameNo + ",16进制卡号:" + Card16H+ ',DSFID:' + DSFID + ",硬件序列号:" + SerialNum
                            self.rw15693Signel.emit(3, RemortIPort, "电脑发指令写卡失败!")
                        self.textEdit_9.setText(dispinf)

        elif (len(data) > 0):
            if (data[0] == eval('0xF7')):
                if (len(data) == 8 and data[7] == 0):
                    self.wifiset.plainTextEdit.setPlainText("设置设备WIFI热点参数的指令已传送到设备,30秒后可以获取到设备WIFI连接状态!")

            elif (data[0] == eval('0x1D')):
                if (RemortIPort == self.netparawin.lineEdit_RemoIPort.text()):
                    self.netparawin.plainTextEdit_Disp.setPlainText('1D设置参数指令成功执行!')

        elif (dispcode == 1):
            self.ListAddItem(RemortIPort)

    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):
            self.netparawin = NetParaSetwindow()  # 实例化 网络参数设置窗口

            screen = QDesktopWidget().screenGeometry()
            size = self.netparawin.geometry()
            newLeft = (screen.width() - size.width()) // 2
            newTop = (screen.height() - size.height()) // 2
            self.netparawin.move(newLeft, newTop)

            self.netparawin.setWindowFlags(QtCore.Qt.WindowCloseButtonHint | QtCore.Qt.WindowStaysOnTopHint)

            self.netparawin.lineEdit_ReaderNnm.setText(self.tableWidget.item(currentrow, 0).text())
            self.netparawin.lineEdit_ReaderIP.setText(self.tableWidget.item(currentrow, 1).text())
            self.netparawin.lineEdit_ReaderMask.setText(self.tableWidget.item(currentrow, 2).text())
            self.netparawin.lineEdit_ReaderPort.setText(self.tableWidget.item(currentrow, 3).text())
            self.netparawin.lineEdit_Gatwag.setText(self.tableWidget.item(currentrow, 4).text())
            self.netparawin.lineEdit_GatwayMAC.setText(self.tableWidget.item(currentrow, 5).text())
            self.netparawin.lineEdit_RemoIP.setText(self.tableWidget.item(currentrow, 6).text())
            self.netparawin.lineEdit_RemoMAC.setText(self.tableWidget.item(currentrow, 7).text())
            self.netparawin.lineEdit_Serial.setText(self.tableWidget.item(currentrow, 10).text())
            Search = eval('0x' + self.tableWidget.item(currentrow, 8).text().strip())
            if (Search == 0):
                self.netparawin.radioButton_gatwaybind.setChecked(True)
                self.netparawin.radioButton_RemoMACBind.setChecked(True)
            elif (Search == 1):
                self.netparawin.radioButton_gatwaybind.setChecked(True)
                self.netparawin.radioButton_RemoMACAuto.setChecked(True)
            elif (Search == 2):
                self.netparawin.radioButton_Gatwayauto.setChecked(True)
                self.netparawin.radioButton_RemoMACBind.setChecked(True)
            else:
                self.netparawin.radioButton_Gatwayauto.setChecked(True)
                self.netparawin.radioButton_RemoMACAuto.setChecked(True)

            paracod = self.tableWidget.item(currentrow, 9).text().strip()
            self.netparawin.comboBox_beep.setCurrentIndex(int(paracod[-1:8], 2))
            if (paracod[-2:7] == '1'):
                self.netparawin.checkBox_DHCP.setChecked(True)
            else:
                self.netparawin.checkBox_DHCP.setChecked(False)
            self.netparawin.comboBox_SendEn.setCurrentIndex(int(paracod[-3:6], 2))
            self.netparawin.comboBox_Sendinterval.setCurrentIndex(int(paracod[0:5], 2))

            self.netparawin.label_19.setStyleSheet('color:red;')
            self.netparawin.label_20.setStyleSheet('color:red;')
            self.netparawin.lineEdit_RemoIPort.setStyleSheet('color:blue;')
            self.netparawin.plainTextEdit_Disp.setStyleSheet('color:blue;')
            self.netparawin.lineEdit_RemoIPort.setText(self.textEdit_7.toPlainText().strip())
            self.netparawin.show()
            self.setEnabled(False)

            self.netparawin.netparaSignel.connect(self.GetNetParaSetSignal)  # 将设置网络参数窗口的 信号 绑定给 主窗口的 槽函数
        else:
            QMessageBox.critical(self, "警告", "     请选择一台在线设备!", QMessageBox.Yes)

    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([eval('0xA6')])  # 搜索在线设备的指令码
        s.sendto(sdata, ('255.255.255.255', Bindprot))  # 发送搜索同网段内所有在线设备的广播指令
        self.ListAddItem(
            get_time() + 'SendTo:' + ("255.255.255.255:" + str(Bindprot) + "            ")[0:22] + " Data:A6")

        sdata = bytes([eval('0xA8')])  # 查询设备版本型号、固件更新日期
        s.sendto(sdata, ('255.255.255.255', Bindprot))  # 发送搜索同网段内所有在线设备的广播指令
        self.ListAddItem(
            get_time() + 'SendTo:' + ("255.255.255.255:" + str(Bindprot) + "            ")[0:22] + " Data:A8")

    def PBClear_click(self):
        self.listWidget.clear()
        self.textEdit_9.setText('')

    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 DisableSendAge(self, remortiport, data):  # 接收到读卡器上传的数据包立即回应,否则读卡器会继续上传三次
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        senddata = bytes(
            [105, data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8]])  # 接收到的数包前9字节,首字节改为 69H 来回应
        s.sendto(senddata, (Remoip, Reprot))

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(senddata)):
            SendInf = SendInf + '%02X ' % (senddata[num])
        self.ListAddItem(SendInf)

    def PBGetmodel_click(self):
        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        comb = bytes([eval('0xA8')])  # A8是指令码
        s.sendto(comb, (Remoip, Reprot))  # 发送A8指令查询设备版本型号

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(comb)):
            SendInf = SendInf + '%02X ' % (comb[num])
        self.ListAddItem(SendInf)

    def PBSendDispBeep_click(self):
        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])

        DevNo = int(self.textEdit_8.toPlainText())
        HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号

        dispinf = self.textEdit.toPlainText() + '                                    '  # 加空格是为了全屏显示
        DispStr = dispinf[0:34]
        disb = bytes(DispStr, encoding='gbk')  # 将要显示的文字转bytes

        comb = bytes([eval('0x5A')])  # 5A是指令码
        comb = comb + bytes.fromhex(HexStr)  # 2字节机号
        comb = comb + bytes([self.CBbeep.currentIndex()])  # 1字节蜂鸣代码
        comb = comb + bytes([self.spinBox.value()])  # 1字节显示时长
        sdata = comb + disb  # 34字节显示文字

        s.sendto(sdata, (Remoip, Reprot))  # 发送5A指令驱动读卡器显示文字+蜂鸣响声

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    def PBSwitchOff_click(self):
        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
        DelayTime = self.spinBox_2.value()
        DelHexStr = '%02X%02X' % (DelayTime % 256, DelayTime // 256)  # 2字节继电器延时
        switch = 'E%d' % (self.CBSwitch.currentIndex())  # 所选的继电器

        sdata = bytes([eval('0x78')])  # 78是指令码
        sdata = sdata + bytes.fromhex(HexStr)  # 2字节机号
        sdata = sdata + bytes.fromhex(switch)  # 1字节继电器代号
        sdata = sdata + bytes.fromhex(DelHexStr)  # 2字节延长时间
        s.sendto(sdata, (Remoip, Reprot))  # 发送78指令驱动读卡器关闭已开启的继电器

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    def PBSwitchOn_click(self):
        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
        DelayTime = self.spinBox_2.value()
        DelHexStr = '%02X%02X' % (DelayTime % 256, DelayTime // 256)  # 2字节继电器延时
        switch = 'F%d' % (self.CBSwitch.currentIndex())  # 所选的继电器

        sdata = bytes([eval('0x78')])  # 78是指令码
        sdata = sdata + bytes.fromhex(HexStr)  # 2字节机号
        sdata = sdata + bytes.fromhex(switch)  # 1字节继电器代号
        sdata = sdata + bytes.fromhex(DelHexStr)  # 2字节延长时间
        s.sendto(sdata, (Remoip, Reprot))  # 发送78指令驱动读卡器开启继电器

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    def PBSendDispTTS_click(self):
        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])

        DevNo = int(self.textEdit_8.toPlainText())
        HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号

        DelayTime = self.spinBox_2.value()
        DelHexStr = '%02X%02X' % (DelayTime % 256, DelayTime // 256)  # 2字节继电器延时

        voice = self.spinBox_3.value()  # 语音大小,最大声音值16
        if (voice > 16):
            voice = 16

        DispStr = self.textEdit.toPlainText() + '                                    '  # 加空格是为了全屏显示
        disb = bytes(DispStr, encoding='gbk')  # 将要显示的文字转bytes

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

        switch = 'F%d' % (self.CBSwitch.currentIndex())  # 所选的继电器
        sufb = bytes([eval('0x55'), eval('0xaa'), eval('0x66'), eval('0x99')])  # 固定的抗干扰后缀

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

        s.sendto(sdata, (Remoip, Reprot))  # 发送5C指令驱动读卡器显示文字+蜂鸣响声+开关继电器+播报TTS语音

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    def PBSendDispSpk_click(self):
        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])

        DevNo = int(self.textEdit_8.toPlainText())
        HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号

        DelayTime = self.spinBox_2.value()
        DelHexStr = '%02X%02X' % (DelayTime % 256, DelayTime // 256)  # 2字节延时

        DispStr = self.textEdit.toPlainText() + '                                    '  # 加空格是为了全屏显示
        disb = bytes(DispStr, encoding='gbk')  # 将要显示的文字转bytes

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

        switch = 'F%d' % (self.CBSwitch.currentIndex())  # 所选的继电器
        sufb = bytes([eval('0x55'), eval('0xaa'), eval('0x66'), eval('0x99')])  # 固定的抗干扰后缀

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

        s.sendto(sdata, (Remoip, Reprot))  # 发送5B指令驱动读卡器显示文字+蜂鸣响声+开关继电器+播报固定组合语音

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    def PBReadCard_click(self):
        keystr = self.textEdit_4.toPlainText().strip()  # 卡片认证密码
        if (is_valid_hex(keystr) == False or len(bytes.fromhex(keystr)) != 6):
            self.ListAddItem("卡密码输入错误!")
            self.textEdit_4.setFocus()
            return

        cardstr = self.textEdit_3.toPlainText().strip()
        if (is_valid_hex(cardstr) == False or len(bytes.fromhex(cardstr)) != 4):  # 16进制卡号
            self.ListAddItem("卡号输入错误!")
            self.textEdit_3.setFocus()
            return

        self.textEdit_5.setPlainText('')
        global LastBuf
        LastBuf = bytes(9)

        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
        sector = self.CBPage.currentIndex()  # 读写扇区号
        auth = self.CBauth.currentIndex()  # 密码认证方式

        sdata = bytes([eval('0x3B')])  # 3B是指令码
        sdata = sdata + bytes.fromhex(HexStr)  # 2字节机号
        sdata = sdata + bytes([1])  # 1字节扇区个数
        sdata = sdata + bytes.fromhex(cardstr)  # 4字节16进制卡号 00000000 表示可操作任意卡
        sdata = sdata + bytes([sector])  # 1字节扇区号
        sdata = sdata + bytes([auth])  # 1字节密码认证方式
        sdata = sdata + bytes.fromhex(keystr)  # 6字节密码

        s.sendto(sdata, (Remoip, Reprot))  # 发送3B指令驱动读写器读卡

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    def PBWriteCard_click(self):
        keystr = self.textEdit_4.toPlainText().strip()  # 卡片认证密码
        if (is_valid_hex(keystr) == False or len(bytes.fromhex(keystr)) != 6):
            self.ListAddItem("卡密码输入错误!")
            self.textEdit_4.setFocus()
            return

        cardstr = self.textEdit_3.toPlainText().strip()
        if (is_valid_hex(cardstr) == False or len(bytes.fromhex(cardstr)) != 4):  # 16进制卡号
            self.ListAddItem("卡号输入错误!")
            self.textEdit_3.setFocus()
            return

        Writestr = self.textEdit_5.toPlainText().strip()  # 48字节写卡数据
        if (is_valid_hex(Writestr) == False or len(bytes.fromhex(Writestr)) != 48):
            self.ListAddItem("写卡数据输入错误,请输入48个16进制写卡数据!")
            self.textEdit_5.setFocus()
            return

        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
        sector = self.CBPage.currentIndex()  # 读写扇区号
        auth = self.CBauth.currentIndex()  # 密码认证方式

        sdata = bytes([eval('0x3D')])  # 3D是指令码
        sdata = sdata + bytes.fromhex(HexStr)  # 2字节机号
        sdata = sdata + bytes([1])  # 1字节扇区个数
        sdata = sdata + bytes.fromhex(cardstr)  # 4字节16进制卡号 00000000 表示可操作任意卡
        sdata = sdata + bytes([sector])  # 1字节扇区号
        sdata = sdata + bytes([auth])  # 1字节密码认证方式
        sdata = sdata + bytes.fromhex(keystr)  # 6字节卡密码
        sdata = sdata + bytes.fromhex(Writestr)  # 48字节写卡数据
        sdata = sdata + bytes.fromhex("55AA6699")  # 4字节防错

        s.sendto(sdata, (Remoip, Reprot))  # 发送3D指令驱动读写器写卡

        SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[0:22] + ' Data:'  # 为方便开发,打印出详细的指令
        for num in range(0, len(sdata)):
            SendInf = SendInf + '%02X ' % (sdata[num])
        self.ListAddItem(SendInf)

    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)
            newkey = self.textEdit_6.toPlainText().strip()  # 16字节新卡密码
            if (is_valid_hex(newkey) == False or len(bytes.fromhex(newkey)) != 16):
                self.ListAddItem("卡新密钥输入错误!")
                self.textEdit_6.setFocus()
                return

            keystr = self.textEdit_4.toPlainText().strip()  # 卡片认证密码
            if (is_valid_hex(keystr) == False or len(bytes.fromhex(keystr)) != 6):
                self.ListAddItem("卡密码输入错误!")
                self.textEdit_4.setFocus()
                return

            cardstr = self.textEdit_3.toPlainText().strip()
            if (is_valid_hex(cardstr) == False or len(bytes.fromhex(cardstr)) != 4):  # 16进制卡号
                self.ListAddItem("卡号输入错误!")
                self.textEdit_3.setFocus()
                return

            remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
            FieldsList = remortiport.split(':')
            Remoip = FieldsList[0]
            Reprot = int(FieldsList[1])
            DevNo = int(self.textEdit_8.toPlainText())
            HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
            sector = self.CBPage.currentIndex()  # 读写扇区号
            auth = self.CBauth.currentIndex()  # 密码认证方式
            auth = auth + self.ChangeKey.currentIndex() * 2  # 密码修改方式

            sdata = bytes([eval('0x3A')])  # 3A是指令码
            sdata = sdata + bytes.fromhex(HexStr)  # 2字节机号
            sdata = sdata + bytes([1])  # 1字节扇区个数
            sdata = sdata + bytes.fromhex(cardstr)  # 4字节16进制卡号 00000000 表示可操作任意卡
            sdata = sdata + bytes([sector])  # 1字节扇区号
            sdata = sdata + bytes([auth])  # 1字节密码认证方式
            sdata = sdata + bytes.fromhex(keystr)  # 6字节卡密码
            sdata = sdata + bytes.fromhex(newkey)  # 16字节新密码
            sdata = sdata + bytes.fromhex("55AA6699")  # 4字节防错

            s.sendto(sdata, (Remoip, Reprot))  # 发送3A指令驱动读写器更改卡片密钥
            SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[
                                               0:22] + ' Data:'  # 为方便开发,打印出详细的指令
            for num in range(0, len(sdata)):
                SendInf = SendInf + '%02X ' % (sdata[num])
            self.ListAddItem(SendInf)

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

    def SetRW(self, obj):
        remortiport = self.textEdit_7.toPlainText().strip()  # 需要驱动设备的 IP、端口
        FieldsList = remortiport.split(':')
        Remoip = FieldsList[0]
        Reprot = int(FieldsList[1])
        DevNo = int(self.textEdit_8.toPlainText())
        HexStr = '%02X%02X' % (DevNo % 256, DevNo // 256)  # 2字节机号
        sector = self.CBPage.currentIndex()  # 读写扇区号
        auth = self.CBauth.currentIndex()  # 密码认证方式

        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(HexStr)  # 2字节机号
            sdata = sdata + bytes([0])  # 读0个扇区数据
            sdata = sdata + bytes.fromhex("55AA6699")  # 4字节确认码
            s.sendto(sdata, (Remoip, Reprot))  # 发送4B指令将读写器设为只读卡号
            SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[
                                               0:22] + ' Data:'  # 为方便开发,打印出详细的指令
            for num in range(0, len(sdata)):
                SendInf = SendInf + '%02X ' % (sdata[num])
            self.ListAddItem(SendInf)
        else:
            keystr = self.textEdit_4.toPlainText().strip()  # 卡片认证密码
            if (is_valid_hex(keystr) == False or len(bytes.fromhex(keystr)) != 6):
                self.ListAddItem("卡密码输入错误!")
                self.textEdit_4.setFocus()
                return

            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]) + bytes.fromhex(
                keystr)  # 1字节的扇区号及密码认证类型 + 6字节卡认证密码 ,如果读多个扇区也按此结构加入,可以开通全部的16个扇区
            sdata = sdata + bytes.fromhex("55AA6699")  # 4字节确认码
            s.sendto(sdata, (Remoip, Reprot))  # 发送4B指令将读写器设为主动读取扇区
            SendInf = get_time() + 'SendTo:' + (remortiport + '                      ')[
                                               0:22] + ' Data:'  # 为方便开发,打印出详细的指令
            for num in range(0, len(sdata)):
                SendInf = SendInf + '%02X ' % (sdata[num])
            self.ListAddItem(SendInf)

    def PBWifiSet_click(self):
        self.wifiset = WifiSetWindow()  # 实例化 wifi热点参数设置窗口

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

        self.wifiset.setWindowFlags(  # 使能最小化按钮 .WindowMinimizeButtonHint
            QtCore.Qt.WindowCloseButtonHint |  # 使能关闭按钮
            QtCore.Qt.WindowStaysOnTopHint)  # 窗体总在最前端

        self.wifiset.groupBox.setVisible(False)
        self.wifiset.comboBox_Sendmode.setCurrentIndex(1)
        self.wifiset.label_7.setStyleSheet('color: red;')
        self.wifiset.lineEdit_RemoIPort.setStyleSheet("color: red;")
        self.wifiset.show()

        self.setEnabled(False)

        self.wifiset.WifiSignel.connect(self.GetWiFiWindoSignal)  # 将wifi热点参数窗口的 信号 绑定给 主窗口的 槽函数
        self.wifiset.lineEdit_RemoIPort.setText(self.textEdit_7.toPlainText().strip())

    def PB15693RW_click(self):
        self.ISO15693RW = ISO15693RW()

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

        self.ISO15693RW.setWindowFlags(  # 使能最小化按钮 .WindowMinimizeButtonHint
            QtCore.Qt.WindowCloseButtonHint |  # 使能关闭按钮
            QtCore.Qt.WindowStaysOnTopHint)  # 窗体总在最前端
        self.ISO15693RW.lineEdit_RemoIPort.setText(self.textEdit_7.toPlainText().strip())
        self.ISO15693RW.lineEdit_Mask.setText('0000000000000000')

        self.ISO15693RW.label_19.setStyleSheet('color:red;')
        self.ISO15693RW.label_20.setStyleSheet('color:red;')
        self.ISO15693RW.lineEdit_RemoIPort.setStyleSheet('color:blue;')
        self.ISO15693RW.lineEdit_disp.setStyleSheet('color:blue;')

        self.ISO15693RW.show()

        self.setEnabled(False)

        self.ISO15693RW.iso15693Signel.connect(self.Getiso15693Signal)


# =======================================================================================================================
def get_time():
    current_time = datetime.datetime.now()
    current_time_str = current_time.strftime("%H:%M:%S.%f")[:-3]
    return current_time_str + ' '


def is_valid_hex(input_str):
    input_str = input_str.replace(" ", "")
    try:
        if (len(bytes.fromhex(input_str)) == len(input_str) / 2):
            return True
        else:
            return False
    except:
        return False


def GetHexIPAdd(inputstr):
    try:
        FieldsList = inputstr.split('.')
        HexIPAdd = '%02X%02X%02X%02X' % (
        int(FieldsList[0]), int(FieldsList[1]), int(FieldsList[2]), int(FieldsList[3]))  # 4字节设备IP
        if (len(HexIPAdd) != 8):
            HexIPAdd = "00000000"
    except:
        HexIPAdd = "00000000"
    return HexIPAdd


def IsIport(inputstr):
    try:
        remortiport = inputstr.strip()
        FieldsList = remortiport.split(':')
        Remoip = GetHexIPAdd(FieldsList[0])
        Reprot = int(FieldsList[1])
        if (Remoip == "00000000"):
            return False
        else:
            return True
    except:
        return False


def get_mac_address(ip_address):  # 不能返回本机MAC
    # 初始化 用正则表达式're'编译出匹配MAC地址的正则表达式对象
    patt_mac = re.compile('([a-f0-9]{2}[-:]){5}[a-f0-9]{2}', re.I)
    # ping
    os.popen('ping -n 1 -w 500 {} > nul'.format(ip_address))
    # 然后使用'arp'命令获取该IP地址对应的MAC地址 返回一个类文件对象 可以通过 read 方法获取命令的输出结果
    arp_file = os.popen('arp -a {}'.format(ip_address))
    # 使用正则表达式'self.patt_mac'在输出结果中查找符合 MAC 地址格式的字符串 并返回找到的第一个匹配项 即 IP 对应的 MAC 地址
    mac_addr = patt_mac.search(arp_file.read())

    # 根据正则表达式对象匹配MAC地址 如果匹配到了就返回MAC地址 否则返回None
    if mac_addr:
        mac_addr = mac_addr.group()
        return mac_addr
    else:
        return 'FF-FF-FF-FF-FF-FF'


def get_default_gateway():
    gateways = netifaces.gateways()
    return gateways['default'][netifaces.AF_INET][0]  # 获取IPv4的默认网关


# =======================================================================================================================
if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWindow = MainWindow()

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

    mainWindow.setWindowTitle("RFID网络读卡器测试工具 Ver:2024.04.01")
    mainWindow.show()

    mainWindow.TEPort.setPlainText("39169")

    mainWindow.textEdit.setPlainText("欢迎您使用我们的网络读卡器!")
    mainWindow.textEdit_2.setPlainText("欢迎您使用我们的网络读卡器!")
    mainWindow.textEdit_3.setPlainText("00000000")
    mainWindow.textEdit_4.setPlainText("FFFFFFFFFFFF")
    mainWindow.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")
    mainWindow.textEdit_6.setPlainText("FF FF FF FF FF FF FF 07 80 69 FF FF FF FF FF FF")
    mainWindow.textEdit_7.setPlainText('255.255.255.255:39169')
    mainWindow.textEdit_8.setPlainText('00000')
    mainWindow.spinBox.setValue(20)
    mainWindow.spinBox_2.setValue(200)
    mainWindow.spinBox_3.setValue(10)
    mainWindow.CBauth.setCurrentIndex(0)

    mainWindow.listWidget.setStyleSheet("color: blue;")
    mainWindow.textEdit_9.setStyleSheet("color: blue;")
    mainWindow.label_19.setStyleSheet("color: red;")
    mainWindow.PBSearch.setStyleSheet("color: red;")

    if sys.platform == 'linux' or sys.platform == 'mac':  # linux、mac系统获取电脑所有网卡IP
        ips = [ip.split('/')[0] for ip in os.popen("ip addr | grep 'inet '|awk '{print $2}'").readlines()]
        for i in ips:
            mainWindow.CBIP.addItem(i)
    else:
        addrs = socket.getaddrinfo(socket.gethostname(), None)  # Windows系统获取电脑所有网卡IP
        for item in addrs:
            if ':' not in item[4][0]:
                mainWindow.CBIP.addItem(item[4][0])

    if mainWindow.CBIP.count() > 0:
        Bindip = mainWindow.CBIP.currentText()
        Bindprot = int(mainWindow.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))

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

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

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

        changip = 1

    sys.exit(app.exec_())

源码下载:Python网络读写器windows、linux系统源码_NFC发送SOF指令资源-CSDN文库

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

津津有味道

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值