ID读卡器TCP协议QT小程序开发

电子说

1.3w人已加入

描述

ID卡网络读卡器TCP协议QT小程序开发。

TCP(传输控制协议,Transmission Control Protocol)是互联网中最核心、最基本的协议之一。以下是对TCP协议的详细介绍:

一、基本概念
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它工作在OSI模型的第四层,即传输层,为用户提供可靠的、有序的和无差错的数据传输服务。TCP协议与UDP协议是传输层的两大主要协议,但两者在设计上有明显的不同:TCP提供的是可靠的数据传输服务,而UDP则更注重传输的速度和效率。

二、技术特点
1.面向连接:TCP在传输数据之前,必须先建立连接,确保数据的传输路径是可靠的。连接建立后,TCP会维护一个连接状态,包括序列号、窗口大小等信息,用于保证数据传输的有序性和可靠性。
2.可靠传输:TCP通过确认重传机制、滑动窗口机制、超时重传机制等方式,确保数据在传输过程中不会丢失、不会重复、不会乱序。具体来说,TCP会给每个报文段分配一个序列号,接收方根据序列号确认数据的顺序和完整性。如果接收方发现数据丢失或乱序,会要求发送方重传。
3.字节流传输:TCP将应用层发送的数据划分成以字节为单位的报文段,并进行序列号标记。这种方式能够确保数据在传输过程中不会被拆分或丢失,从而保证数据的完整性。
4.全双工通信:TCP允许双方在任何时候都能发送数据,为此TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。
三、工作原理
1.连接建立:TCP连接建立采用三次握手过程。首先,客户端向服务器发送一个SYN报文段,请求建立连接。服务器收到后,回复一个SYN-ACK报文段,表示同意建立连接并确认客户端的SYN报文段。最后,客户端再发送一个ACK报文段,确认服务器的SYN-ACK报文段。至此,TCP连接建立完成。
2.数据传输:在连接建立后,双方可以开始传输数据。TCP会将应用层发送的数据划分成报文段,并添加TCP头部信息(包括序列号、窗口大小等),然后交给IP层进行传输。接收方收到报文段后,会进行校验和检查、序列号确认等操作,确保数据的完整性和顺序性。如果发现问题,会要求发送方重传。
3.连接终止:TCP连接终止采用四次挥手过程。首先,一方发送一个FIN报文段,表示要关闭连接。另一方收到后,回复一个ACK报文段,表示同意关闭连接但还有数据要发送。当所有数据发送完毕后,另一方再发送一个FIN报文段,表示关闭连接。最后,接收方回复一个ACK报文段,确认连接关闭。至此,TCP连接终止完成。
四、应用场景
TCP协议广泛应用于需要可靠传输的场合,如HTTP、FTP等协议都基于TCP协议进行数据传输。此外,TCP还用于数据库连接、远程登录等需要稳定连接的场合。

综上所述,TCP协议是一种高效、稳定且可靠的传输层协议,它通过多种机制确保数据的可靠传输和有序性。在互联网传输中,TCP协议发挥着重要作用。

Qt

QT开发示例的UI界面如下: 

Qt

mainWindow.cpp代码如下: 

 

bool listening=false;               //sock侦听标志
QByteArray sendData;                //发送数据缓冲
 
 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{    
    ui- >setupUi(this);
 
    ui- >scrollArea- >setVisible(false);    
    ui- >scrollArea- >move(180,40);
 
    ui- >scrollArea_wifi- >setVisible(false);
    ui- >scrollArea_wifi- >move(250,130);
 
    ui- >scrollArea_config- >setVisible(false);
    ui- >scrollArea_config- >move(250,130);
 
    ui- >groupBox_dhcp- >setVisible(false);
 
    QStringList ips = MyClass::getAllIPAddresses();
    foreach (QString ip, ips) {
        ui- >CBIP- >addItem(ip);
    }
    if(ui- >CBIP- >count()< 1){
        QMessageBox::information(NULL, "提示", "未搜索到本机的网卡,系统不能正常运行!");
        delete ui;
    }
    sockinit();
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
//通讯报文显示-----------------------------------------------------------------------------------------------------
void MainWindow::listadditems(int ctr,QString listinfo){
    switch (ctr){
    case 0:
        if(ui- >listWidget- >count() >10){
            ui- >listWidget- >clear();
        }
        ui- >listWidget- >addItem(listinfo);
        ui- >listWidget- >setCurrentRow(ui- >listWidget- >count()-1);
        break;
    case 1:
        ui- >textEdit_msg- >setText(listinfo);
    }
}
 
//广播发送搜索所有在线的设备-------------------------------------------------------------------------------------------
void MainWindow::on_PBSearch_clicked()
{
    int n = ui- >tableWidget- >rowCount();//总行数
    for (int i = 0;i <= n;i++)
        ui- >tableWidget- >removeRow(0);//遍历删除第0行
 
 
    QHostAddress broadcastAddress("255.255.255.255");
    quint16 port1 = 39169;
    sendData.clear();
    sendData.append(0xA6);
    udpSocket- >writeDatagram(sendData.constData(), sendData.size(), QHostAddress::Broadcast, port1);        //搜索所有在线设备
    QString  dispinf=MyClass::getsystime()+" Send To: "+("255.255.255.255:"+QString::number(port1)+"             ").mid(0,22)+"A6" ;
    listadditems(0,dispinf);
 
    sendData.clear();
    sendData.append(0xA8);
    udpSocket- >writeDatagram(sendData.constData(), sendData.size(), QHostAddress::Broadcast, port1);      //查询在线设备型号、固件日期
    dispinf=MyClass::getsystime()+" Send To: "+("255.255.255.255:"+QString::number(port1)+"             ").mid(0,22)+"A8" ;
    listadditems(0,dispinf);
}
 
void MainWindow::sockinit(){    //初始化Socket UDP侦听端口
    try{
        if(!listening){
            QString ipstr=ui- >CBIP- >currentText();
            QHostAddress localeip(ipstr);
            quint16 port=ui- >TEPort- >toPlainText().toUInt();
            udpSocket =new QUdpSocket(this);
            udpSocket- >bind(localeip,port);                         //udpSocket- >bind(QHostAddress::Any,port);  这个方式是绑定所有网卡,这样发不出广播包
            connect(udpSocket, &QUdpSocket::readyRead, this,&MainWindow::read_data);
            listening=true;
            listadditems(0,MyClass::getsystime()+" Sock已启动侦听"+ipstr+":"+ui- >TEPort- >toPlainText());
        }
    }
    catch(_exception)
    {
        listening=false;
        udpSocket- >close();
        listadditems(0,MyClass::getsystime()+" Sock侦听已关闭!");
    }
}
 
//Socket UDP端口接收数据---------------------------------------------------------------------------------------------------------
void MainWindow::read_data(){
    unsigned char databuff[1024] = {0};
    QHostAddress ip;
    quint16 port;
    qint64 buflen = udpSocket- >readDatagram((char *)databuff, sizeof(databuff), &ip, &port);
    QString str;
    for (int i = 0; i < buflen; i++)
    {
        str +=QString::asprintf("%02X ", databuff[i]);
    }    
    QString  dispinf=MyClass::getsystime()+" Receive: "+(ip.toString()+":"+QString::number(port)+"             ").mid(0,22)+str ;
    listadditems(0,dispinf);
 
    switch (databuff[0]){
    case 0xc1:
        Analyze_c1(ip, port,databuff,buflen);          //解析读取IC卡卡号
        break;
 
    case 0xc3:
        Analyze_c3(ip, port,databuff,buflen);          //主动读取M1卡扇区数据的返回
        break;
 
    case 0x3c:
        Analyze_3c(ip, port,databuff,buflen);          //主动写M1卡扇区数据的返回
        break;
 
    case 0xc5:
        Analyze_c5(ip, port,databuff,buflen);          //指定区号密钥读取M1扇区数据返回
        break;
 
    case 0xcd:
        Analyze_cd(ip, port,databuff,buflen);          //指定区号密钥写数据到M1卡扇区返回
        break;
 
    case 0xd1:
        Analyze_d1(ip, port,databuff,buflen);          //解析读取ID卡卡号
        break;
 
    case 0xcf:
    case 0xdf:
        Analyze_cf_df(ip, port,databuff,buflen);       //解析IC、ID卡离开读卡器
        break;
 
    case 0xf2:
        Analyze_f2(ip, port,databuff,buflen);          //在线设备响应搜索指令的返回、读卡器上电开机上传设备信息
        break;
 
    case 0xf6:
        Analyze_f6(ip, port,databuff,buflen);          //在线设备响应查询型号、固件日期指令的返回
        break;
 
    case 0xa4:
        Analyze_a4(ip, port,databuff,buflen);          //查询WIFI叁数的返回
        break;
 
    case 0x4b:
        Analyze_4b(ip, port,databuff,buflen);          //设置主动读M1卡扇区号及认证密钥的返回
        break;
 
    default:
        break;
    }
}
 
//设置主动读M1卡扇区号及认证密钥的返回---------------------------------------------------------------------------------------------------
void MainWindow::Analyze_4b(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    ui- >label_msg_2- >setText("设备IP:"+IPAddress+",机号:"+DeviceNumber+",设置读卡扇区及认证密钥成功!");
    ui- >textEdit_msg- >setText("设备IP:"+IPAddress+",机号:"+DeviceNumber+",设置读卡扇区及认证密钥成功!");
    if(ui- >checkBox_Resp- >isChecked()){Respondinfo("设置读卡扇区及认证密钥成功!",ip,port,DeviceNumber);}  //回应驱动设备显示+蜂鸣响声
}
 
//确认接收到的信息----------------------------------------------------------------------------------------------------------------
void MainWindow::DisableSendAgain(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    QString SendHex=MyClass::getsystime()+" Send To: "+(ip.toString()+":"+QString::number(port)+"             ").mid(0,22)+"69 " ;
    sendData.clear();
    sendData.append(0x69);
    for (int i=1;i< 9;i++){
        sendData.append(databuff[i]);
        SendHex=SendHex+QString::asprintf("%02X ", databuff[i]);
    }
    udpSocket- >writeDatagram(sendData.constData(), sendData.size(), QHostAddress(ip), port);    
    listadditems(0,SendHex+"      确定接收,不要再次发送此帧数据啦...");
}
 
//解析读取IC卡卡号-------------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_c1(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    DisableSendAgain(ip, port,databuff,buflen);//确认接收到的信息,否则同一信息读卡器会重发三次
 
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    QString FrameNumber=QString::asprintf("%05d",databuff[7]+databuff[8]*256);    //数据包号
    QString CardnoHexZ=QString::asprintf("%02X%02X%02X%02X", databuff[10],databuff[11],databuff[12],databuff[13]);  //16进制卡号正码
    QString CardnoHexF=QString::asprintf("%02X%02X%02X%02X", databuff[13],databuff[12],databuff[11],databuff[10]);  //16进制卡号反码
    bool status;
    QString Cardno8H10D=QString::asprintf("%010u",CardnoHexF.toUInt(&status,16));  //转8H10D反码卡号
    QString SerialNumber="";        //设备全球唯一硬件序号
    for (int i=14;itextEdit_M1UID- >setText(CardnoHexZ);
 
    if(ui- >checkBox_Resp- >isChecked()){Respondinfo(MyClass::getsysdatetime()+"卡号:"+Cardno8H10D,ip,port,DeviceNumber);}  //回应驱动设备显示+蜂鸣响声
}
 
//主动读取扇区数据的返回--------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_c3(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    QString CardnoHex="";
    for (int i=12;i< 16;i++){
        CardnoHex=CardnoHex+QString::asprintf("%02X", databuff[i]);
    }
 
    int j=databuff[10]*48;
    int m=databuff[11]*48;
 
    for(int i=0;i< m;i++){
        readcardbuf[j+i]=databuff[16+i];
    }
 
    if((databuff[10]+databuff[11]) >=databuff[9]){
        m=databuff[9]*48;
        QString DataHex="";
        for (int i=0;i< m;i++){
            DataHex=DataHex+QString::asprintf("%02X ",readcardbuf[i]);
        }
        ui- >textEdit_data- >setPlainText(DataHex);
        QString DispInf="读取M1卡扇区数据成功,设备IP:"+IPAddress+",机号:"+DeviceNumber+",16进制卡号:"+CardnoHex;
        listadditems(1,DispInf);
        ui- >textEdit_M1UID- >setText(CardnoHex);
 
        if(ui- >checkBox_Resp- >isChecked()){Respondinfo(MyClass::getsysdatetime()+"卡号:"+CardnoHex,ip,port,DeviceNumber);}  //回应驱动设备显示+蜂鸣响声
    }
}
 
//主动写M1卡扇区数据指令的返回--------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_3c(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
 
    if(databuff[7]+databuff[8] >=writcardlen){      //全部写卡数据已经发送完毕
        ui- >textEdit_msg- >setPlainText("设备IP:"+IPAddress+",机号:"+DeviceNumber+",写卡成功!");
        if(ui- >checkBox_Resp- >isChecked()){Respondinfo("写扇区数据成功!",ip,port,DeviceNumber);}  //回应驱动设备显示+蜂鸣响声
    }else{
        QByteArray RespBuff;             //写卡数据超过4个扇区,需要继续发送
        RespBuff.append(0x3c);           //功能码
        quint16 devno=0;
        RespBuff.append(devno % 256);    //机号低位
        RespBuff.append(devno / 256);    //机号高位,高低位都为0表示所有机
        RespBuff.append(writcarepoi);    //当前已写扇区指针
 
        int j=writcardlen - writcarepoi;
        if(j >4){j=4;};
        RespBuff.append(j);              //本次总计写扇区数,一次最多写4扇区,多于4扇区要分次写入
 
        for (int i=0;i< 4;i++){           //加入4个字节的卡号,卡号为0表示可以操作任意卡
            RespBuff.append(1-1);
        }
 
        for (int i=0;i< j*48;i++){
            RespBuff.append(writecardbuf[writcarepoi*48+i]);
        }
 
        udpSocket- >writeDatagram(RespBuff.constData(), RespBuff.size(), QHostAddress(ip), port);
 
        QString SendHex=MyClass::getsystime()+" Send To: "+(ip.toString()+":"+QString::asprintf("%d",port)+"             ").mid(0,22);
        SendHex=SendHex+MyClass::ByteArrayToHexString(RespBuff);
        listadditems(0,SendHex);
 
        writcarepoi=writcarepoi+j;
    }
}
 
//指定区号密钥读取M1扇区数据返回-----------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_c5(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    QString CardnoHex="";    
    QString  DispInf="";
    for (int i=8;i< 12;i++){
        CardnoHex=CardnoHex+QString::asprintf("%02X", databuff[i]);
    }
    QString Sector=QString::asprintf("%d", databuff[12]);    //扇区号
 
    DispInf="读取M1卡"+Sector+"扇区数据";
    switch (databuff[13]){
    case 0:
        {
            QString DataHex="";
            for (int i=0;i< 48;i++){
                DataHex=DataHex+QString::asprintf("%02X ", databuff[14+i]);
            }
            DispInf=DispInf+"成功,设备IP:"+IPAddress+",机号:"+DeviceNumber+",16进制卡号:"+CardnoHex;
            ui- >textEdit_data- >setPlainText(DataHex);
            break;
        }
    case 8:
            DispInf=DispInf+"失败,设备IP:"+IPAddress+",机号:"+DeviceNumber+",没有卡片在感应区!";
            break;
    case 12:
            DispInf=DispInf+"失败,设备IP:"+IPAddress+",机号:"+DeviceNumber+",16进制卡号:"+CardnoHex+",卡密码认证失败!";
            break;
    default:
            DispInf=DispInf+"失败,设备IP:"+IPAddress+",机号:"+DeviceNumber+",错误代码:"+QString::asprintf("%d", databuff[13]);
            break;
    }
    listadditems(1,DispInf);
    ui- >textEdit_M1UID- >setText(CardnoHex);
 
    if(ui- >checkBox_Resp- >isChecked()){Respondinfo(DispInf,ip,port,DeviceNumber);}  //回应驱动设备显示+蜂鸣响声
}
 
//指定区号密钥写数据到M1卡扇区返回状态---------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_cd(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4])+"."+QString::asprintf("%d", databuff[5]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[6]+databuff[7]*256);   //设备自编机号
    QString CardnoHex="";
    for (int i=9;i< 13;i++){
        CardnoHex=CardnoHex+QString::asprintf("%02X", databuff[i]); //16进制卡号
    }
    QString Sector=QString::asprintf("%d", databuff[13]);           //扇区号
    QString Pages=QString::asprintf("%d", databuff[8]);             //本次操作的扇区总数
    QString  DispInf="";
    if(databuff[1]==0x3a){
        DispInf="修改M1卡"+Sector+"扇区密钥";
    }else if(databuff[1]==0x3d){
        DispInf="写数据到M1卡"+Sector+"扇区";
    }
    switch (databuff[14]){
    case 0:
            DispInf=DispInf+"成功,设备IP:"+IPAddress+",机号:"+DeviceNumber+",16进制卡号:"+CardnoHex;
            break;
    case 8:
            DispInf=DispInf+"失败,设备IP:"+IPAddress+",机号:"+DeviceNumber+",没有卡片在感应区!";
            break;
    case 12:
            DispInf=DispInf+"失败,设备IP:"+IPAddress+",机号:"+DeviceNumber+",16进制卡号:"+CardnoHex+",卡密码认证失败!";
            break;
    default:
            DispInf=DispInf+"失败,设备IP:"+IPAddress+",机号:"+DeviceNumber+",错误代码:"+QString::asprintf("%d", databuff[13]);
            break;
    }
    listadditems(1,DispInf);
    if(ui- >checkBox_Resp- >isChecked()){Respondinfo(DispInf,ip,port,DeviceNumber);}  //回应驱动设备显示+蜂鸣响声
}
 
//解析读取ID卡卡号-----------------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_d1(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    DisableSendAgain(ip, port,databuff,buflen);//确认接收到的信息,否则同一信息读卡器会重发三次
 
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    QString FrameNumber=QString::asprintf("%05d",databuff[7]+databuff[8]*256);    //数据包号
    QString CardnoHexZ=QString::asprintf("%02X%02X%02X%02X%02X", databuff[9],databuff[10],databuff[11],databuff[12],databuff[13]);  //16进制卡号正码,databuff[13]为厂商代码
    QString CardnoHexF=QString::asprintf("%02X%02X%02X%02X", databuff[12],databuff[11],databuff[10],databuff[9]);   //16进制卡号反码,databuff[13]为厂商代码
    bool status;
    QString Cardno8H10D=QString::asprintf("%010u",CardnoHexF.toUInt(&status,16));  //转8H10D反码卡号
    QString SerialNumber="";        //设备全球唯一硬件序号
    for (int i=14;icheckBox_Resp- >isChecked()){Respondinfo(MyClass::getsysdatetime()+"卡号:"+Cardno8H10D,ip,port,DeviceNumber);}  //回应驱动设备显示+蜂鸣响声
}
 
//解析ICID卡离开读卡器-----------------------------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_cf_df(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    DisableSendAgain(ip, port,databuff,buflen);//确认接收到的信息,否则同一信息读卡器会重发三次
 
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    QString FrameNumber=QString::asprintf("%05d",databuff[7]+databuff[8]*256);    //数据包号
    int infotype=databuff[9];           //数据说明,1表示只读取UID卡号
    int cardnolen=databuff[10];         //UID卡号长度
    QString CardnoHexZ="";              //16进制卡号正码
    for (int i=0;i< cardnolen;i++){
        CardnoHexZ=CardnoHexZ+QString::asprintf("%02X", databuff[11+i]);
    }
    QString CardnoHexF=CardnoHexZ.mid(6,2)+CardnoHexZ.mid(4,2)+CardnoHexZ.mid(2,2)+CardnoHexZ.mid(0,2);   //16进制卡号反码
    bool status;
    QString Cardno8H10D=QString::asprintf("%010u",CardnoHexF.toUInt(&status,16));  //转8H10D反码卡号
    QString SerialNumber="";        //设备全球唯一硬件序号
    for (int i=11+cardnolen;itableWidget- >insertRow(row);
    QTableWidgetItem* item = new QTableWidgetItem;
    item- >setText(DeviceNumber);
    ui- >tableWidget- >setItem(row,0, item);
 
    item = new QTableWidgetItem;
    item- >setText(IPAddress);
    ui- >tableWidget- >setItem(row,1, item);
 
    item = new QTableWidgetItem;
    item- >setText(mask);
    ui- >tableWidget- >setItem(row,2, item);
 
    item = new QTableWidgetItem;
    item- >setText(PortStr);
    ui- >tableWidget- >setItem(row,3, item);
 
    item = new QTableWidgetItem;
    item- >setText(GetWay);
    ui- >tableWidget- >setItem(row,4, item);
 
    item = new QTableWidgetItem;
    item- >setText(GetWayMAC);
    ui- >tableWidget- >setItem(row,5, item);
 
    item = new QTableWidgetItem;
    item- >setText(ServerIp);
    ui- >tableWidget- >setItem(row,6, item);
 
    item = new QTableWidgetItem;
    item- >setText(ServerMAC);
    ui- >tableWidget- >setItem(row,7, item);
 
    item = new QTableWidgetItem;
    item- >setText(MACPara);
    ui- >tableWidget- >setItem(row,8, item);
 
    item = new QTableWidgetItem;
    item- >setText(NetPara);
    ui- >tableWidget- >setItem(row,9, item);
 
    item = new QTableWidgetItem;
    item- >setText(ModuleNumber);
    ui- >tableWidget- >setItem(row,10, item);
 
    item = new QTableWidgetItem;
    item- >setText(STMAC);
    ui- >tableWidget- >setItem(row,11, item);
 
    item = new QTableWidgetItem;
    item- >setText(SerialNumber);
    ui- >tableWidget- >setItem(row,12, item);
 
    item = new QTableWidgetItem;
    item- >setText(CHMAC);
    ui- >tableWidget- >setItem(row,13, item);
 
    for (int i=0;i<=13;i++){
        ui- >tableWidget- >resizeColumnToContents(i); //自动列宽
    }
}
 
//响应查询设备型号固件日期指令的返回---------------------------------------------------------------------------------------------------
void MainWindow::Analyze_f6(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[1])+"."+QString::asprintf("%d", databuff[2])+"."+QString::asprintf("%d", databuff[3])+"."+QString::asprintf("%d", databuff[4]);  //设备IP
    QString DeviceNumber=QString::asprintf("%05d",databuff[5]+databuff[6]*256);   //设备自编机号
    int NameLen=databuff[7];    //设备型号名称长度
    QByteArray namebuf;         //设备型号
    for (int i=0;i< NameLen;i++){
        namebuf.append(databuff[8+i]);
    }
    QString namestr=namebuf;
 
    int VersionDateLen=databuff[8 + NameLen];  //固件日期长度
    QByteArray verbuf;   //固件日期
    for (int i=0;i< VersionDateLen;i++){
        verbuf.append(databuff[8 + NameLen + 1+i]);
    }
    QString verdatestr=verbuf;
 
    int rowCount = ui- >tableWidget- >rowCount();
    for (int row = 0; row < rowCount; ++row) {
         QTableWidgetItem *item = ui- >tableWidget- >item(row, 1);
         QString ipstr = item- >text();
         if (IPAddress==ipstr){
            item = new QTableWidgetItem;
            item- >setText(namestr);
            ui- >tableWidget- >setItem(row,14, item);
            ui- >tableWidget- >resizeColumnToContents(14); //自动列宽
 
            item = new QTableWidgetItem;
            item- >setText(verdatestr);
            ui- >tableWidget- >setItem(row,15, item);
            ui- >tableWidget- >resizeColumnToContents(15); //自动列宽
            return;
         }
    }
}
 
//查询wifi连接状态---------------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_a4(QHostAddress ip,quint16 port,unsigned char databuff[], qint64 buflen)
{
    QString IPAddress=QString::asprintf("%d", databuff[7])+"."+QString::asprintf("%d", databuff[8])+"."+QString::asprintf("%d", databuff[9])+"."+QString::asprintf("%d", databuff[10]); //设备IP地址,广域网上使用,一般不对此IP回应,而是对数据流的 ip及端口 回应
    ui- >listWidget_wifi- >addItem("WIFI的IP地址:"+IPAddress);
    QString mask=QString::asprintf("%d", databuff[11])+"."+QString::asprintf("%d", databuff[12])+"."+QString::asprintf("%d", databuff[13])+"."+QString::asprintf("%d", databuff[14]);       //设备掩码
    ui- >listWidget_wifi- >addItem("WIFI子网掩码:"+mask);
    QString MACStr=QString::asprintf("%02X", databuff[15])+"-"+QString::asprintf("%02X", databuff[16])+"-"+QString::asprintf("%02X", databuff[17])+"-"+QString::asprintf("%02X", databuff[18])+"-"+QString::asprintf("%02X", databuff[19])+"-"+QString::asprintf("%02X", databuff[20]); //MAC地址
    ui- >listWidget_wifi- >addItem("WIFI_MAC地址:"+MACStr);
    QString GateWay=QString::asprintf("%d", databuff[21])+"."+QString::asprintf("%d", databuff[22])+"."+QString::asprintf("%d", databuff[23])+"."+QString::asprintf("%d", databuff[24]); //设备网关
    ui- >listWidget_wifi- >addItem("WIFI网关地址:"+GateWay);
    QString GatewayMAC=QString::asprintf("%02X", databuff[25])+"-"+QString::asprintf("%02X", databuff[26])+"-"+QString::asprintf("%02X", databuff[27])+"-"+QString::asprintf("%02X", databuff[28])+"-"+QString::asprintf("%02X", databuff[29])+"-"+QString::asprintf("%02X", databuff[30]); //网关MAC
    ui- >listWidget_wifi- >addItem("网关 MAC地址:"+GatewayMAC);
    switch (databuff[31]){
    case 0:
        ui- >listWidget_wifi- >addItem("WIFI网络状态:已连接wifi");
        break;
    case 1:
        ui- >listWidget_wifi- >addItem("WIFI网络状态:连接失败!");
        break;
    case 2:
        ui- >listWidget_wifi- >addItem("WIFI网络状态:已初始化!");
        break;
    default:
        ui- >listWidget_wifi- >addItem("WIFI网络状态:未初始化!");
        break;
    }
    QByteArray devname;
    for(int i=0 ;i< databuff[32];i++){
        devname.append(databuff[34+i]);
    }
    QString devnamestr=devname;
    ui- >listWidget_wifi- >addItem("读卡器  名称:"+devnamestr);
 
    QByteArray wifname;
     for(int i=0 ;i< databuff[33];i++){
         wifname.append(databuff[44+i]);
     }
     QString wifinamestr=wifname;
     ui- >listWidget_wifi- >addItem("WIFI热点名称:"+wifinamestr);
}
 
//更换不同的网卡----------------------------------------------------------------------------------------------------
void MainWindow::on_CBIP_currentIndexChanged(int index)
{
    if (listening){
        disconnect(udpSocket, &QUdpSocket::readyRead, this,&MainWindow::read_data);
        udpSocket- >close();
        listening=false;
        listadditems(0,MyClass::getsystime()+" Sock侦听已关闭!");
    }
    sockinit();
}
 
 
void MainWindow::on_PBClear_clicked()
{
    ui- >listWidget- >clear();
    ui- >textEdit_msg- >setText("");
}
 
//在在线设备列表中选取一台设备IP端口
void MainWindow::on_tableWidget_cellClicked(int row, int column)
{
    int currentRow = ui- >tableWidget- >currentIndex().row();
    QString DeviceNumber = ui- >tableWidget- >item(currentRow,0)- >text();
    QString IPAddress= ui- >tableWidget- >item(currentRow,1)- >text();
    QString PortStr= ui- >tableWidget- >item(currentRow,3)- >text();
    ui- >textEdit_DeviceNumber- >setText(DeviceNumber);
    ui- >textEdit_remoiport- >setText(IPAddress+":"+PortStr);
 
    ui- >New_Nember- >setText(DeviceNumber);
    ui- >New_IP- >setText(IPAddress);
    ui- >New_ServerIP- >setText( ui- >tableWidget- >item(currentRow,6)- >text());
    ui- >ServerMAC- >setText( ui- >tableWidget- >item(currentRow,7)- >text());
    ui- >New_Mask- >setText( ui- >tableWidget- >item(currentRow,2)- >text());
    ui- >New_Gateway- >setText( ui- >tableWidget- >item(currentRow,4)- >text());
    ui- >GateWayMac- >setText( ui- >tableWidget- >item(currentRow,5)- >text());
    ui- >New_Port- >setText( ui- >tableWidget- >item(currentRow,3)- >text());
    ui- >Serial_Number- >setText( ui- >tableWidget- >item(currentRow,10)- >text());
 
    quint8 functionid=ui- >tableWidget- >item(currentRow,9)- >text().toInt();
    if((functionid % 2) >0){ui- >checkBox_beep- >setChecked(true);}else{ui- >checkBox_beep- >setChecked(false);}
    functionid=functionid/2;
    if((functionid % 2) >0){ui- >checkBox_dhcp- >setChecked(true);}else{ui- >checkBox_dhcp- >setChecked(false);}
    functionid=functionid/2;
    ui- >comboBox_out- >setCurrentIndex(functionid % 2);
    functionid=functionid/2;
    functionid=functionid % 8;
    if (functionid<=4){ui- >comboBox_in- >setCurrentIndex(functionid);}else{ui- >comboBox_in- >setCurrentIndex(0);}
 
    quint8 automac=ui- >tableWidget- >item(currentRow,8)- >text().toInt();
    switch (automac){
    case 0:
        ui- >radioButton1- >setChecked(false);
        ui- >radioButton2- >setChecked(true);
        ui- >radioButton3- >setChecked(false);
        ui- >radioButton4- >setChecked(true);
        break;
    case 1:
        ui- >radioButton1- >setChecked(true);
        ui- >radioButton2- >setChecked(false);
        ui- >radioButton3- >setChecked(false);
        ui- >radioButton4- >setChecked(true);
        break;
    case 2:
        ui- >radioButton1- >setChecked(false);
        ui- >radioButton2- >setChecked(true);
        ui- >radioButton3- >setChecked(true);
        ui- >radioButton4- >setChecked(false);
        break;
    default:
        ui- >radioButton1- >setChecked(true);
        ui- >radioButton2- >setChecked(false);
        ui- >radioButton3- >setChecked(true);
        ui- >radioButton4- >setChecked(false);
        break;
    }
}
 
 
void MainWindow::on_PBEditpara_clicked()
{
    int currentRow = ui- >tableWidget- >currentIndex().row();
    if (currentRow< 0){
        QMessageBox::critical(this, "警告", "请选择一台在线设备再执行此功能!", QMessageBox::Ok);
    }else{
        ui- >scrollArea_wifi- >setVisible(false);
        ui- >scrollArea- >setVisible(true);
        ui- >scrollArea_config- >setVisible(false);
    }
}
 
//将sendData缓冲数据发送到指定的设备IP端口---------------------------------------------------------------------------------------
void MainWindow:: SendBuffAct()
{
    QString RemoIPort=ui- >textEdit_remoiport- >toPlainText();
    QStringList liststr = RemoIPort.split(":");
    QHostAddress Remoip(liststr[0]);
    quint16 Remoport=liststr[1].toUInt();
 
    udpSocket- >writeDatagram(sendData.constData(), sendData.size(), QHostAddress(Remoip), Remoport);
 
    QString SendHex=MyClass::getsystime()+" Send To: "+(Remoip.toString()+":"+QString::asprintf("%d",Remoport)+"             ").mid(0,22);
    SendHex=SendHex+MyClass::ByteArrayToHexString(sendData);
    listadditems(0,SendHex);
}
 
//驱动设备蜂鸣响声+文字显示-------------------------------------------------------------------------------------------------
void MainWindow::on_PBSendDispBeep_clicked()
{
    sendData.clear();
    sendData.append(0x5A);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    sendData.append(ui- >CBbeep- >currentIndex());       //蜂鸣响声代码,255表示不响声
    sendData.append(ui- >spinBox_dispdelay- >value());   //文字显示时长,
    QString dispstr=ui- >textEdit_disp- >toPlainText()+"                                  ";  //加空格是为了确保满屏34位显示
    QByteArray Dispbyte=dispstr.toLocal8Bit();
    for(int i=0;i< 34;i++){
        sendData.append(Dispbyte[i]);
    }
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
//驱动设备蜂鸣响声-----------------------------------------------------------------------------------------------------------
void MainWindow::on_PBbeep_clicked()
{
    sendData.clear();
    sendData.append(0x96);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    sendData.append(ui- >CBbeep- >currentIndex());       //蜂鸣响声代码
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
//驱动设备开启继电器----------------------------------------------------------------------------------------------------------
void MainWindow::on_PBSwitchOn_clicked()
{
    sendData.clear();
    sendData.append(0x78);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    QString swithno="F"+QString::asprintf("%d",ui- >CBSwitch- >currentIndex());
    bool status;
    sendData.append(swithno.toUInt(&status,16));       //选择继电器
    quint16 deltime=ui- >spinBox_swit- >value();
    sendData.append(deltime % 256);                    //开启延时低位
    sendData.append(deltime / 256);                    //开启延时高位
 
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
//驱动设备关闭继电器----------------------------------------------------------------------------------------------------------
void MainWindow::on_PBSwitchOff_clicked()
{
    sendData.clear();
    sendData.append(0x78);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    QString swithno="E"+QString::asprintf("%d",ui- >CBSwitch- >currentIndex());
    bool status;
    sendData.append(swithno.toUInt(&status,16));       //选择继电器
    quint16 deltime=ui- >spinBox_swit- >value();
    sendData.append(deltime % 256);                    //延时低位
    sendData.append(deltime / 256);                    //延时高位
 
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
//驱动设备显示文字+蜂鸣响声+播报TTS语音+开启继电器开关------------------------------------------------------------------------------
void MainWindow::on_PBSendDispTTS_clicked()
{
    if(ui- >spinBox_voice- >value() >16){ui- >spinBox_voice- >setValue(16);} //tts最大语音取值16
    QString strls="[v"+QString::asprintf("%d",ui- >spinBox_voice- >value())+"]";
    strls=strls+ui- >textEdit_tts- >toPlainText().trimmed();
    QByteArray SpeakArr=strls.toLocal8Bit();         //TS语音转换为Ansi码
    quint8 speakbytes=SpeakArr.size();
    quint8 dispbytes=34;                //双行显示屏显示长度34,四行屏显示长度72
 
    sendData.clear();
    sendData.append(0x5c);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    sendData.append(ui- >CBbeep- >currentIndex());       //蜂鸣响声代码,取值255表示不响
 
    QString swithno="F"+QString::asprintf("%d",ui- >CBSwitch- >currentIndex());
    bool status;
    sendData.append(swithno.toUInt(&status,16));       //选择继电器
    quint16 deltime=ui- >spinBox_swit- >value();
    sendData.append(deltime % 256);                    //延时低位
    sendData.append(deltime / 256);                    //延时高位
 
    sendData.append(ui- >spinBox_dispdelay- >value());   //文字显示时长,
    quint8 begindisp =0;                               //在显示屏中的哪个位置开始显示,一般取0
    sendData.append(begindisp);
    sendData.append(dispbytes);                        //显示文字长度
    sendData.append(speakbytes);                       //tts语音长茺
 
    QString dispstr=ui- >textEdit_disp- >toPlainText()+"                                  ";  //加空格是为了确保满屏34位显示
    QByteArray Dispbyte=dispstr.toLocal8Bit();
    for(int i=0;i< dispbytes;i++){
        sendData.append(Dispbyte[i]);       //显示信息
    }
    for(int i=0;i< speakbytes;i++){
        sendData.append(SpeakArr[i]);       //TTS语音信息
    }
 
    sendData.append(0x55);      //防干扰后缀
    sendData.append(0xaa);
    sendData.append(0x66);
    sendData.append(0x99);
 
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
//驱动设备显示文字+蜂鸣响声+播报固定组合语音+开启继电器开关------------------------------------------------------------------------------
void MainWindow::on_PBSendDispSpk_clicked()
{
    QByteArray speakcode; //选择加入要播报的语音代码,最多可加入21个,各语音代码参看 语音列表栏
    speakcode.append(36);speakcode.append(1);speakcode.append(11);speakcode.append(2);speakcode.append(10);
    speakcode.append(3);speakcode.append(17);speakcode.append(4);speakcode.append(16);speakcode.append(5);speakcode.append(15);
 
    qint8 lensy=speakcode.size();                      //语音代码长度
    quint8 begindisp =0;                               //在显示屏中的哪个位置开始显示,一般取0
    quint8 dispbytes=34;                               //双行显示屏显示长度34
 
    sendData.clear();
    sendData.append(0x5b);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    sendData.append(ui- >CBbeep- >currentIndex());       //蜂鸣响声代码,取值255表示不响
 
    QString swithno="F"+QString::asprintf("%d",ui- >CBSwitch- >currentIndex());
    bool status;
    sendData.append(swithno.toUInt(&status,16));       //选择继电器
    quint16 deltime=ui- >spinBox_swit- >value();
    sendData.append(deltime % 256);                    //延时低位
    sendData.append(deltime / 256);                    //延时高位
 
    sendData.append(ui- >spinBox_dispdelay- >value());   //文字显示时长,
 
    sendData.append(begindisp);                        //显示起始位置
    sendData.append(dispbytes);                        //显示字符串长度
    sendData.append(lensy);                            //语音代码条数
 
    QString dispstr=ui- >textEdit_disp- >toPlainText()+"                                  ";  //加空格是为了确保满屏34位显示
    QByteArray Dispbyte=dispstr.toLocal8Bit();
    for(int i=0;i< dispbytes;i++){
        sendData.append(Dispbyte[i]);       //显示信息
    }
    for(int i=0;i< lensy;i++){
        sendData.append(speakcode[i]);      //语音信息
    }
 
    sendData.append(0x55);      //防干扰后缀
    sendData.append(0xaa);
    sendData.append(0x66);
    sendData.append(0x99);
 
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
//指定扇区密钥读取M1卡扇区数据----------------------------------------------------------------------------------------
void MainWindow::on_PBReadCard_clicked()
{
    unsigned char cardnobuf[4];      //卡号
    unsigned char keybuf[6];         //密钥
    int keylen;
    int cardnolen;
 
    QString cardnostr ="00000000";   // ui- >textEdit_M1UID- >toPlainText().trimmed(); "00000000"表示可能操作感应区内任意卡,如要操作特定卡可指定卡号
    cardnolen=MyClass::checkhexdata(cardnostr,cardnobuf);
    if(cardnolen< 4){
        QMessageBox::critical(NULL, "提示", "请输入8位正确的16进制卡号!");
        ui- >textEdit_M1UID- >setFocus();
        return;
    }
 
    QString keyinf = ui- >textEdit_authkey- >toPlainText().trimmed();
    keylen=MyClass::checkhexdata(keyinf,keybuf);
    if(keylen< 6){
        QMessageBox::critical(NULL, "提示", "请输入12位正确的16进制卡密码!");
        ui- >textEdit_authkey- >setFocus();
        return;
    }
 
    sendData.clear();
    sendData.append(0x3b);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    sendData.append(0x01);                             //本次操作的区数
    for (int i=0 ;i< 4;i++){                            //指定读写的卡号,全为0 表示可读写任意卡
        sendData.append(cardnobuf[i]);
    }
    sendData.append(ui- >CBPage- >currentIndex());       //本次操作的扇区号
    sendData.append(ui- >CBauth- >currentIndex());       //为1以B密码来验证旧密码,为0以A密码来验证旧密码
    for (int i=0 ;i< 6;i++){
        sendData.append(keybuf[i]);                    //认证密钥
    }
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
 
//指定扇区密钥写入数据到M1卡扇区----------------------------------------------------------------------------------------
void MainWindow::on_PBWriteCard_clicked()
{
    unsigned char cardnobuf[4];      //卡号
    unsigned char keybuf[6];         //密钥   
    int keylen;
    int cardnolen;
    int datalen;
 
    QString cardnostr ="00000000";   // ui- >textEdit_M1UID- >toPlainText().trimmed(); "00000000"表示可能操作感应区内任意卡,如要操作特定卡可指定卡号
    cardnolen=MyClass::checkhexdata(cardnostr,cardnobuf);
    if(cardnolen< 4){
        QMessageBox::critical(NULL, "提示", "请输入8位正确的16进制卡号!");
        ui- >textEdit_M1UID- >setFocus();
        return;
    }
 
    QString keyinf = ui- >textEdit_authkey- >toPlainText().trimmed();
    keylen=MyClass::checkhexdata(keyinf,keybuf);
    if(keylen< 6){
        QMessageBox::critical(NULL, "提示", "请输入12位正确的16进制卡密码!");
        ui- >textEdit_authkey- >setFocus();
        return;
    }
 
    QString datastr = ui- >textEdit_data- >toPlainText().trimmed();
    datastr=datastr.replace(" ","");
    datalen=MyClass::checkhexdata(datastr,writecardbuf);
    if(datalen< 48){
        int answ=QMessageBox::question (this, "警告", "有效的写卡数据不足一扇区48字节,是否要补0写入到指定扇区?", QMessageBox::Ok, QMessageBox::Cancel);
        if (answ !=1024){
            ui- >textEdit_data- >setFocus();
            return;
        }
        for (int i=datalen;i< 48;i++){
            writecardbuf[i]=0;
        }
    }else {
        if (datalen >48){
            int answ=QMessageBox::question (this, "警告", "本指令只可以写一个扇区数据,是否将前48个数据写入到指定扇区?", QMessageBox::Ok, QMessageBox::Cancel);
            if (answ !=1024){
                ui- >textEdit_data- >setFocus();
                return;
            }
        }
    }
 
    sendData.clear();
    sendData.append(0x3d);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    sendData.append(0x01);                             //本次操作的区数
    for (int i=0 ;i< 4;i++){                            //指定读写的卡号,全为0 表示可读写任意卡
        sendData.append(cardnobuf[i]);
    }
    sendData.append(ui- >CBPage- >currentIndex());       //本次操作的扇区号
    sendData.append(ui- >CBauth- >currentIndex());       //为1以B密码来验证旧密码,为0以A密码来验证旧密码
    for (int i=0 ;i< 6;i++){
        sendData.append(keybuf[i]);                    //认证密钥
    }
    for (int i=0 ;i< 48;i++){
        sendData.append(writecardbuf[i]);                    //写卡数据
    }
 
    sendData.append(0x55);      //防干扰后缀
    sendData.append(0xaa);
    sendData.append(0x66);
    sendData.append(0x99);
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
//修改M1卡扇区密钥-------------------------------------------------------------------------------------------------
void MainWindow::on_PBChangeKey_clicked()
{
    int answ=QMessageBox::question (this, "警告", "执行此操作前请记住卡片新密钥,否则卡片将报废!是否继续?", QMessageBox::Ok, QMessageBox::Cancel);
    if (answ !=1024){
        ui- >textEdit_data- >setFocus();
        return;
    }
    unsigned char cardnobuf[4];      //卡号
    unsigned char keybuf[6];         //密钥
    unsigned char newkeybuf[20];     //新密钥
    int keylen;
    int cardnolen;
    int newkeylen;
 
    QString cardnostr ="00000000";   // ui- >textEdit_M1UID- >toPlainText().trimmed(); "00000000"表示可能操作感应区内任意卡,如要操作特定卡可指定卡号
    cardnolen=MyClass::checkhexdata(cardnostr,cardnobuf);
    if(cardnolen< 4){
        QMessageBox::critical(NULL, "提示", "请输入8位正确的16进制卡号!");
        ui- >textEdit_M1UID- >setFocus();
        return;
    }
 
    QString keyinf = ui- >textEdit_authkey- >toPlainText().trimmed();
    keylen=MyClass::checkhexdata(keyinf,keybuf);
    if(keylen< 6){
        QMessageBox::critical(NULL, "提示", "请输入12位正确的16进制卡密码!");
        ui- >textEdit_authkey- >setFocus();
        return;
    }
 
    QString newkey = ui- >textEdit_newkey- >toPlainText().trimmed();
    newkeylen=MyClass::checkhexdata(newkey,newkeybuf);
    if(newkeylen< 16){
        QMessageBox::critical(NULL, "提示", "请输16进制 6字节A密码+4字节控制位+6字节B密码 !");
        ui- >textEdit_newkey- >setFocus();
        return;
    }
 
    sendData.clear();
    sendData.append(0x3a);                             //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);                      //机号低位
    sendData.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    sendData.append(0x01);                             //本次操作的区数
    for (int i=0 ;i< 4;i++){                            //指定读写的卡号,全为0 表示可读写任意卡
        sendData.append(cardnobuf[i]);
    }
    sendData.append(ui- >CBPage- >currentIndex());       //本次操作的扇区号
    quint8 auth=ui- >CBauth- >currentIndex();            //为1以B密码来验证旧密码,为0以A密码来验证旧密码
    auth=auth+ui- >ChangeKey- >currentIndex()*2;         //修改A、B、控制位
    sendData.append(auth);
 
    for (int i=0 ;i< 6;i++){
        sendData.append(keybuf[i]);                    //认证密钥
    }
    for (int i=0 ;i< 16;i++){
        sendData.append(newkeybuf[i]);                 //新A密钥、控制位、B密钥
    }
 
    sendData.append(0x55);      //防干扰后缀
    sendData.append(0xaa);
    sendData.append(0x66);
    sendData.append(0x99);
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
 
void MainWindow::on_PBSetRW_clicked()
{
    ui- >scrollArea- >setVisible(false);
    ui- >scrollArea_wifi- >setVisible(false);
    ui- >scrollArea_config- >setVisible(true);
}
 
 
void MainWindow::on_PBcopylist_clicked()
{
    QString listinf;
    int row=ui- >listWidget- >count();
    if (row< 1){
        return;
    }else{
        for (int i=0;i< row;i++){
            QListWidgetItem *item = ui- >listWidget- >item(i);
            listinf=listinf+item- >text()+"n";
        }
        QClipboard *clipboard = QApplication::clipboard();
        clipboard- >setText(listinf);
        QMessageBox::information(this, "提示", "显示数据报文已拷贝到剪切板");
    }
}
 
//接收到刷卡数据立即回应--------------------------------------------------------------------------
void MainWindow::Respondinfo(QString Dispinf,QHostAddress ip,quint16 port,QString DeviceNumber)
{
    QByteArray RespBuff;
    RespBuff.append(0x5A);                             //功能码
    quint16 devno=DeviceNumber.toUInt();
    RespBuff.append(devno % 256);                      //机号低位
    RespBuff.append(devno / 256);                      //机号高位,高低位都为0表示所有机
    RespBuff.append(ui- >CBbeep- >currentIndex());       //蜂鸣响声代码,255表示不响声
    RespBuff.append(ui- >spinBox_dispdelay- >value());   //文字显示时长,
    QString dispstr=Dispinf+"                                  ";  //加空格是为了确保满屏34位显示
    QByteArray Dispbyte=dispstr.toLocal8Bit();
    for(int i=0;i< 34;i++){
        RespBuff.append(Dispbyte[i]);
    }
 
    udpSocket- >writeDatagram(RespBuff.constData(), RespBuff.size(), QHostAddress(ip), port);
 
    QString SendHex=MyClass::getsystime()+" Send To: "+(ip.toString()+":"+QString::asprintf("%d",port)+"             ").mid(0,22);
    SendHex=SendHex+MyClass::ByteArrayToHexString(RespBuff);
    listadditems(0,SendHex);
}
 
void MainWindow::on_pushButton_9_clicked()
{
    ui- >scrollArea- >setVisible(false);
}
 
 
void MainWindow::on_pushButton_clicked()
{
    ui- >New_ServerIP- >setText(ui- >CBIP- >currentText().trimmed());
}
 
 
void MainWindow::on_pushButton_2_clicked()
{
    ui- >New_ServerIP- >setText("255.255.255.255");
    ui- >ServerMAC- >setText("FF-FF-FF-FF-FF-FF");
    ui- >radioButton1- >setChecked(true);
    ui- >radioButton2- >setChecked(false);
}
 
 
void MainWindow::on_pushButton_4_clicked()
{
    ui- >New_ServerIP- >setText("119.29.167.63");
    ui- >ServerMAC- >setText("FF-FF-FF-FF-FF-FF");
    ui- >radioButton1- >setChecked(true);
    ui- >radioButton2- >setChecked(false);
}
 
 
 
void MainWindow::on_pushButton_3_clicked()
{
    QString serverip=ui- >CBIP- >currentText().trimmed();
    ui- >New_ServerIP- >setText(serverip);
    QString servermac=MyClass::getMacByIp(serverip);
    servermac=servermac.replace(":","-");
    if(servermac==""){servermac="FF-FF-FF-FF-FF-FF";}
    ui- >ServerMAC- >setText(servermac);
}
 
 
void MainWindow::on_pushButton_7_clicked()
{
    QString gateway=ui- >New_Gateway- >text().trimmed();
    QString gatemac=MyClass::getMacByIp(gateway);
    gatemac=gatemac.replace(":","-");
    if (gatemac==""){gatemac="FF-FF-FF-FF-FF-FF";}
    ui- >GateWayMac- >setText(gatemac);
}
 
 
void MainWindow::on_pushButton_8_clicked()
{
    if (ui- >radioButton1- >isChecked()){ui- >ServerMAC- >setText("FF-FF-FF-FF-FF-FF");}
    if (ui- >radioButton3- >isChecked()){ui- >GateWayMac- >setText("FF-FF-FF-FF-FF-FF");}
 
    QString newip=ui- >New_IP- >text().trimmed();
    if (!MyClass::isValidIP(newip)){
        QMessageBox::critical(NULL, "提示", "请输入有效的设备IP!");
        ui- >New_IP- >setFocus();
        return;
    }
    QString newmask=ui- >New_Mask- >text().trimmed();
    if (!MyClass::isValidIP(newmask)){
        QMessageBox::critical(NULL, "提示", "请输入有效的设备掩码!");
        ui- >New_Mask- >setFocus();
        return;
    }
    QString newserverip=ui- >New_ServerIP- >text().trimmed();
    if (!MyClass::isValidIP(newserverip)){
        QMessageBox::critical(NULL, "提示", "请输入有效的远程服务器ip!");
        ui- >New_ServerIP- >setFocus();
        return;
    }
    QString newgateway=ui- >New_Gateway- >text().trimmed();
    if (!MyClass::isValidIP(newgateway)){
        QMessageBox::critical(NULL, "提示", "请输入有效的网关!");
        ui- >New_Gateway- >setFocus();
        return;
    }
    QString servermac=ui- >ServerMAC- >text().trimmed();
    if (!MyClass::isValidMac(servermac)){
        QMessageBox::critical(NULL, "提示", "请输入有效的远程服务器MAC!");
        ui- >ServerMAC- >setFocus();
        return;
    }
    QString gatemac=ui- >GateWayMac- >text().trimmed();
    if (!MyClass::isValidMac(gatemac)){
        QMessageBox::critical(NULL, "提示", "请输入有效的网关MAC!");
        ui- >GateWayMac- >setFocus();
        return;
    }
    bool ok;
    sendData.clear();
    sendData.append(0xf9);                   //功能码
    QStringList liststr = newip.split(".");  //新IP
    for (int i=0 ;i< 4;i++){
        sendData.append(liststr[i].toInt());
    }
    liststr = newmask.split(".");            //掩码
    for (int i=0 ;i< 4;i++){
        sendData.append(liststr[i].toInt());
    }
    liststr = newserverip.split(".");        //远程服务器IP
    for (int i=0 ;i< 4;i++){
        sendData.append(liststr[i].toInt());
    }
    liststr = servermac.split("-");         //远程服务器MAC
    for (int i=0 ;i< 6;i++){
        sendData.append(liststr[i].toInt(&ok,16));
    }
    liststr = newgateway.split(".");        //网关
    for (int i=0 ;i< 4;i++){
        sendData.append(liststr[i].toInt());
    }
    liststr = gatemac.split("-");           //网关MAC
    for (int i=0 ;i< 6;i++){
        sendData.append(liststr[i].toInt(&ok,16));
    }
    quint16 devno=ui- >New_Nember- >text().toUInt();
    sendData.append(devno % 256);           //机号低位
    sendData.append(devno / 256);           //机号高位,高低位都为0表示所有机
 
    quint16 newport=ui- >New_Port- >text().toInt();
    sendData.append(newport % 256);         //端口低位
    sendData.append(newport / 256);         //端口高位
 
    QString seri=ui- >Serial_Number- >text().trimmed();
    liststr = seri.split("-");              //模块序号
    for (int i=0 ;i< 4;i++){
        sendData.append(liststr[i].toInt());
    }
 
    quint8 searchid=0;
    if (ui- >checkBox_beep- >isChecked()){searchid=searchid+1;}
    if (ui- >radioButton1- >isChecked()){searchid=searchid+2;}
    if (ui- >radioButton3- >isChecked()){searchid=searchid+4;}
    if (ui- >checkBox_dhcp- >isChecked()){searchid=searchid+8;}
    if (ui- >comboBox_out- >currentIndex()==1){searchid=searchid+16;}
    searchid=searchid+ ui- >comboBox_in- >currentIndex()*32;
    sendData.append(searchid);
 
    sendData.append(0x55);      //防干扰后缀
    sendData.append(0xaa);
    sendData.append(0x66);
    sendData.append(0x99);
 
    if (ui- >checkBox_broadcast- >isChecked()){   //使用广播方式发送指令
        QHostAddress broadcastAddress("255.255.255.255");
        quint16 port1 = 39169;
        udpSocket- >writeDatagram(sendData.constData(), sendData.size(), QHostAddress::Broadcast, port1);
        QString  dispinf=MyClass::getsystime()+" Send To: "+("255.255.255.255:"+QString::number(port1)+"             ").mid(0,22) ;
        dispinf=dispinf+MyClass::ByteArrayToHexString(sendData);
        listadditems(0,dispinf);
    }else{
        SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
    }
}
 
 
void MainWindow::on_pushButton_SetTCP_clicked()
{
    sendData.clear();
    sendData.append(0x1d);                  //功能码
    quint16 devno=0;                        //机号,0表示所有机
    sendData.append(devno % 256);           //机号低位
    sendData.append(devno / 256);           //机号高位,高低位都为0表示所有机
    sendData.append(7);                     //指令长度
    sendData.append(0x5c);                  //修改TCP通讯端口功能码
    sendData.append(4);                     //数据长度
 
    quint16 devport=ui- >New_Port- >text().toUInt(); //读卡器端口
    sendData.append(devport % 256);           //低位
    sendData.append(devport / 256);           //高位
 
    quint16 serverport=ui- >lineEdit_TCPRemoPort- >text().toUInt(); //远程TCP服务器端口
    sendData.append(serverport % 256);        //低位
    sendData.append(serverport / 256);        //高位
 
    quint8 crc=sendData[6]^sendData[7]^sendData[8]^sendData[9];    //数据校验位
    sendData.append(crc);
 
    sendData.append(0x55);      //防干扰后缀
    sendData.append(0xaa);
    sendData.append(0x66);
    sendData.append(0x99);
 
    if (ui- >checkBox_broadcast- >isChecked()){   //使用广播方式发送指令
        QHostAddress broadcastAddress("255.255.255.255");
        quint16 port1 = 39169;
        udpSocket- >writeDatagram(sendData.constData(), sendData.size(), QHostAddress::Broadcast, port1);
        QString  dispinf=MyClass::getsystime()+" Send To: "+("255.255.255.255:"+QString::number(port1)+"             ").mid(0,22) ;
        dispinf=dispinf+MyClass::ByteArrayToHexString(sendData);
        listadditems(0,dispinf);
    }else{
        SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
    }
}
 
 
void MainWindow::on_pushButton_SetHttp_clicked()
{
    QString filenamestr=ui- >lineEdit_filename- >text().trimmed();
    QByteArray filebyte=filenamestr.toLocal8Bit();
    if(filebyte.size()< 1){
        QMessageBox::critical(NULL, "提示", "请输入正确的访问文件,可以是.asp\.jsp\.php等脚本文件!");
        ui- >lineEdit_filename- >setFocus();
        return;
    }
    sendData.clear();
    sendData.append(0x1d);                  //功能码
    quint16 devno=0;                        //机号,0表示所有机
    sendData.append(devno % 256);           //机号低位
    sendData.append(devno / 256);           //机号高位,高低位都为0表示所有机
    sendData.append(filebyte.size()+7);     //指令长度
    sendData.append(0x5b);                  //设置http协议读卡器访问文件、端口、提效方式的识别码
    sendData.append(filebyte.size()+4);     //数据长度
    sendData.append(ui- >comboBox_Sendmodel- >currentIndex()); //提交方式
    sendData.append(0xff);
 
    quint16 serverport=ui- >lineEdit_HttpRemoPort- >text().toUInt(); //远程http服务器端口
    sendData.append(serverport % 256);        //低位
    sendData.append(serverport / 256);        //高位
 
    quint8 crc= sendData[6]^ sendData[7]^ sendData[8]^sendData[9];
 
    for(int i=0;i< filebyte.size();i++){
        sendData.append(filebyte[i]);       //访问文件
        crc=crc ^filebyte[i];
    }
    sendData.append(crc);
 
    sendData.append(0x55);      //防干扰后缀
    sendData.append(0xaa);
    sendData.append(0x66);
    sendData.append(0x99);
 
    if (ui- >checkBox_broadcast- >isChecked()){   //使用广播方式发送指令
        QHostAddress broadcastAddress("255.255.255.255");
        quint16 port1 = 39169;
        udpSocket- >writeDatagram(sendData.constData(), sendData.size(), QHostAddress::Broadcast, port1);
        QString  dispinf=MyClass::getsystime()+" Send To: "+("255.255.255.255:"+QString::number(port1)+"             ").mid(0,22) ;
        dispinf=dispinf+MyClass::ByteArrayToHexString(sendData);
        listadditems(0,dispinf);
    }else{
        SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
    }
}
 
 
void MainWindow::on_pushButton_16_clicked()
{
    ui- >scrollArea_wifi- >setVisible(false);
}
 
 
void MainWindow::on_PBClear_2_clicked()
{
    int currentRow = ui- >tableWidget- >currentIndex().row();
    if (currentRow< 0){
        QMessageBox::critical(this, "警告", "请选择一台在线设备再执行此功能!", QMessageBox::Ok);
    }else{
        ui- >scrollArea- >setVisible(false);
        ui- >scrollArea_wifi- >setVisible(true);
        ui- >scrollArea_config- >setVisible(false);
    }
}
 
 
void MainWindow::on_radioButton_IP_toggled(bool checked)
{
    if(ui- >radioButton_IP- >isChecked()){
        ui- >groupBox_dhcp- >setVisible(true);
    }else{
        ui- >groupBox_dhcp- >setVisible(false);
    }
}
 
 
void MainWindow::on_pushButton_SetUp_clicked()
{
    QString wifiName=ui- >lineEdit_SSID- >text().trimmed();
    QByteArray wifiNamearry=wifiName.toUtf8();      //注意编码格式
    if(wifiNamearry.size()< 1 || wifiNamearry.size() >60){
        QMessageBox::critical(NULL, "提示", "WIFI热点名称长度不可大于60,不可为空!");
        ui- >lineEdit_SSID- >setFocus();
        return;
    }
 
    QString wifipass=ui- >lineEdit_Password- >text().trimmed();
    QByteArray wifipassarry=wifipass.toUtf8();      //注意编码格式
    if(wifipassarry.size() >64){
        QMessageBox::critical(NULL, "提示", "WIFI密码长度不可以大于64!");
        ui- >lineEdit_Password- >setFocus();
        return;
    }
 
    sendData.clear();
    sendData.append(0xf7);                  //功能码
    quint16 devno=0;                        //机号,0表示所有机
    sendData.append(devno % 256);           //机号低位
    sendData.append(devno / 256);           //机号高位,高低位都为0表示所有机
    sendData.append(wifiNamearry.size());   //热点名称长度
    quint8 passlen=0;
    if(ui- >checkBox_wifikey- >isChecked()){
        passlen=wifipassarry.size();
    }
    sendData.append(passlen);                //密码长度
 
    int i=0;
    for (i=0;i< wifiNamearry.size();i++){
        sendData.append(wifiNamearry[i]);
    }
    quint8 bytebit=0;
    while (sendData.size()< 65){
        sendData.append(bytebit);
    }
 
    for (i=0;i< passlen;i++){
        sendData.append(wifipassarry[i]);
    }
    while (sendData.size()< 129){
        sendData.append(bytebit);
    }
 
    if(ui- >radioButton_IP- >isChecked()){
        sendData.append(1);
        QString ipstr=ui- >lineEdit_IP- >text().trimmed();
        if (!MyClass::isValidIP(ipstr)){
            QMessageBox::critical(NULL, "提示", "请输入有效的设备IP!");
            ui- >lineEdit_IP- >setFocus();
            return;
        }
        QString mskstr=ui- >lineEdit_mask- >text().trimmed();
        if (!MyClass::isValidIP(mskstr)){
            QMessageBox::critical(NULL, "提示", "请输入正确的读卡器子网掩码!");
            ui- >lineEdit_mask- >setFocus();
            return;
        }
        QString gatewaystr=ui- >lineEdit_gateway- >text().trimmed();
        if (!MyClass::isValidIP(gatewaystr)){
            QMessageBox::critical(NULL, "提示", "请输入正确的读卡器网关!");
            ui- >lineEdit_mask- >setFocus();
            return;
        }
        QStringList liststr = ipstr.split(".");  //IP
        for (int i=0 ;i< 4;i++){
            sendData.append(liststr[i].toInt());
        }
        liststr = mskstr.split(".");             //掩码
        for (int i=0 ;i< 4;i++){
            sendData.append(liststr[i].toInt());
        }
        liststr = gatewaystr.split(".");         //网关
        for (int i=0 ;i< 4;i++){
            sendData.append(liststr[i].toInt());
        }
 
    }else{
        sendData.append(bytebit);
        while (sendData.size()< 142){
            sendData.append(bytebit);
        }
    }
 
    sendData.append(ui- >comboBox_Sendmode- >currentIndex());
 
    sendData.append(0x55);      //防干扰后缀
    sendData.append(0xaa);
    sendData.append(0x66);
    sendData.append(0x99);
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
 
void MainWindow::on_pushButton_Read_clicked()
{
    ui- >listWidget_wifi- >clear();
    sendData.clear();
    sendData.append(0xa4);                  //功能码
    quint16 devno=ui- >textEdit_DeviceNumber- >toPlainText().toUInt();
    sendData.append(devno % 256);           //机号低位
    sendData.append(devno / 256);           //机号高位,高低位都为0表示所有机
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
}
 
 
void MainWindow::on_PBTcpServer_clicked()
{
    this- >tcpserverwin=new TcpServerWin;
    //tcpserverwin- >setWindowFlag(Qt::WindowStaysOnTopHint, true);    //UI窗口置顶显示
    tcpserverwin- >show();
}
 
 
void MainWindow::on_pushButton_close2_clicked()
{
    ui- >scrollArea_config- >setVisible(false);
}
 
//
void MainWindow::on_pushButton_SetConfig_clicked()
{
    unsigned char sendbuff[134];
    sendbuff[0]=0x4b;       //功能码
    sendbuff[1]=0x00;       //2字节机号都取0表示任意机
    sendbuff[2]=0x00;
    sendbuff[3]=0x00;       //主动读卡的扇区数量
    int j=4;
    for(int i=0;i< 16;i++){
        QCheckBox *myCheckBox = this- >findChild< QCheckBox * >("checkBox_s"+QString::asprintf("%d",i));
        QComboBox *myComboBox = this- >findChild< QComboBox * >("CBauth_"+QString::asprintf("%d",i));
        QTextEdit *myTextEdit = this- >findChild< QTextEdit * >("textEdit_key_"+QString::asprintf("%d",i));
 
        unsigned char keybuf[6];         //密钥
        if (myCheckBox- >isChecked()) {
            QString keyinf =myTextEdit- >toPlainText().trimmed();
            int keylen=MyClass::checkhexdata(keyinf,keybuf);
            if(keylen< 6){
                QMessageBox::critical(NULL, "提示", "请输入12位正确的16进制卡密码!");
                myTextEdit- >setFocus();
                return;
            }
            sendbuff[3]=sendbuff[3]+1;         //主动读卡的扇区数量加1
            sendbuff[j]=i;                     //扇区号
            if(myComboBox- >currentIndex() >0){
                sendbuff[j]=sendbuff[j] | 128; //密钥认证方式
            }
            for(int p=0;p< 6;p++){              //认证密钥
                j=j+1;
                sendbuff[j]=keybuf[p];
            }
            j=j+1;
        }
    }
    int qhzs=sendbuff[3];
    sendbuff[4+qhzs*7]=0x55;    //抗干扰后缀
    sendbuff[5+qhzs*7]=0xaa;
    sendbuff[6+qhzs*7]=0x66;
    sendbuff[7+qhzs*7]=0x99;
 
    sendData.clear();
    for(int i=0;i<=7+qhzs*7;i++){
        sendData.append(sendbuff[i]);
    }
    SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
    ui- >label_msg_2- >setText("设置主动读卡扇区及认证密钥的指令已发送...");
}
 
 
void MainWindow::on_PBwritecard_clicked()
{
    int currentRow = ui- >tableWidget- >currentIndex().row();
    if (currentRow< 0){
        QMessageBox::critical(this, "警告", "请选择一台在线设备再执行此功能!", QMessageBox::Ok);
    }else{
        QString writehex = ui- >textEdit_data- >toPlainText().trimmed();
        writehex=writehex.replace(" ","");
        int j=MyClass::checkhexdata(writehex,writecardbuf);
        if((j< 1) || (j%48 !=0) ){
            QMessageBox::critical (this, "警告", "写卡数据输入错误,入写卡字节数必须为 48 的倍数的16进制数据!", QMessageBox::Ok);
            return;
        }
        writcardlen=j/48;
        writcarepoi=0;
        if(writcardlen >0){
            sendData.clear();
            sendData.append(0x3c);           //功能码
            quint16 devno=0;
            sendData.append(devno % 256);    //机号低位
            sendData.append(devno / 256);    //机号高位,高低位都为0表示所有机
            sendData.append(writcarepoi);    //当前已写扇区指针
 
            j=writcardlen - writcarepoi;
            if(j >4){j=4;};
            sendData.append(j);              //本次总计写扇区数,一次最多写4扇区,多于4扇区要分次写入
 
            for (int i=0;i< 4;i++){           //加入4个字节的卡号,卡号为0表示可以操作任意卡
                sendData.append(1-1);
            }
 
            for (int i=0;i< j*48;i++){
                sendData.append(writecardbuf[writcarepoi*48+i]);
            }
            SendBuffAct();        //将sendData缓冲数据发送到指定的设备IP端口
        }
    }
}

审核编辑 黄宇

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分