读卡器获取卡 java 读卡器程序_Python网络

# 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() + '