ID卡网络读卡器TCP协议QT小程序开发。
TCP(传输控制协议,Transmission Control Protocol)是互联网中最核心、最基本的协议之一。以下是对TCP协议的详细介绍:
一、基本概念
TCP是一种面向连接的、可靠的、基于字节流的传输层通信协议。它工作在OSI模型的第四层,即传输层,为用户提供可靠的、有序的和无差错的数据传输服务。TCP协议与UDP协议是传输层的两大主要协议,但两者在设计上有明显的不同:TCP提供的是可靠的数据传输服务,而UDP则更注重传输的速度和效率。
二、技术特点
- 面向连接:TCP在传输数据之前,必须先建立连接,确保数据的传输路径是可靠的。连接建立后,TCP会维护一个连接状态,包括序列号、窗口大小等信息,用于保证数据传输的有序性和可靠性。
- 可靠传输:TCP通过确认重传机制、滑动窗口机制、超时重传机制等方式,确保数据在传输过程中不会丢失、不会重复、不会乱序。具体来说,TCP会给每个报文段分配一个序列号,接收方根据序列号确认数据的顺序和完整性。如果接收方发现数据丢失或乱序,会要求发送方重传。
- 字节流传输:TCP将应用层发送的数据划分成以字节为单位的报文段,并进行序列号标记。这种方式能够确保数据在传输过程中不会被拆分或丢失,从而保证数据的完整性。
- 全双工通信:TCP允许双方在任何时候都能发送数据,为此TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。
三、工作原理
- 连接建立:TCP连接建立采用三次握手过程。首先,客户端向服务器发送一个SYN报文段,请求建立连接。服务器收到后,回复一个SYN-ACK报文段,表示同意建立连接并确认客户端的SYN报文段。最后,客户端再发送一个ACK报文段,确认服务器的SYN-ACK报文段。至此,TCP连接建立完成。
- 数据传输:在连接建立后,双方可以开始传输数据。TCP会将应用层发送的数据划分成报文段,并添加TCP头部信息(包括序列号、窗口大小等),然后交给IP层进行传输。接收方收到报文段后,会进行校验和检查、序列号确认等操作,确保数据的完整性和顺序性。如果发现问题,会要求发送方重传。
- 连接终止:TCP连接终止采用四次挥手过程。首先,一方发送一个FIN报文段,表示要关闭连接。另一方收到后,回复一个ACK报文段,表示同意关闭连接但还有数据要发送。当所有数据发送完毕后,另一方再发送一个FIN报文段,表示关闭连接。最后,接收方回复一个ACK报文段,确认连接关闭。至此,TCP连接终止完成。
四、应用场景
TCP协议广泛应用于需要可靠传输的场合,如HTTP、FTP等协议都基于TCP协议进行数据传输。此外,TCP还用于数据库连接、远程登录等需要稳定连接的场合。
综上所述,TCP协议是一种高效、稳定且可靠的传输层协议,它通过多种机制确保数据的可靠传输和有序性。在互联网传输中,TCP协议发挥着重要作用。
QT开发示例的UI界面如下:
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;i<buflen;i++){
SerialNumber=SerialNumber+QString::asprintf("%02X", databuff[i]);
}
QString DispInf="读取M1卡号,设备IP:"+IPAddress+",机号:"+DeviceNumber+",数据包号:"+FrameNumber+",16进制卡号:"+CardnoHexZ+",转8H10D反码:"+Cardno8H10D+",设备全球唯一序号:"+SerialNumber;
listadditems(1,DispInf);
ui->textEdit_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;i<buflen;i++){
SerialNumber=SerialNumber+QString::asprintf("%02X", databuff[i]);
}
QString DispInf="读取ID卡号,设备IP:"+IPAddress+",机号:"+DeviceNumber+",数据包号:"+FrameNumber+",16进制卡号:"+CardnoHexZ+",转8H10D反码:"+Cardno8H10D+",设备全球唯一序号:"+SerialNumber;
listadditems(1,DispInf);
if(ui->checkBox_Resp->isChecked()){Respondinfo(MyClass::getsysdatetime()+"卡号:"+Cardno8H10D,ip,port,DeviceNumber);} //回应驱动设备显示+蜂鸣响声
}
//解析IC\ID卡离开读卡器-----------------------------------------------------------------------------------------------------------------------------------
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;i<buflen;i++){
SerialNumber=SerialNumber+QString::asprintf("%02X", databuff[i]);
}
QString DispInf="";
if(databuff[0]==0xcf){DispInf="M1卡离开读卡器,";}else{DispInf="ID卡离开读卡器,";}
DispInf=DispInf+"设备IP:"+IPAddress+",机号:"+DeviceNumber+",数据包号:"+FrameNumber+",16进制卡号:"+CardnoHexZ+",转8H10D反码:"+Cardno8H10D+",设备全球唯一序号:"+SerialNumber;
listadditems(1,DispInf);
}
//在线设备响应搜索指令的返回、读卡器上电开机上传设备信息-------------------------------------------------------------------------------------------------------------------
void MainWindow::Analyze_f2(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 mask=QString::asprintf("%d", databuff[5])+"."+QString::asprintf("%d", databuff[6])+"."+QString::asprintf("%d", databuff[7])+"."+QString::asprintf("%d", databuff[8]); //设备掩码
QString PortStr=QString::asprintf("%05d",databuff[9]+databuff[10]*256); //通讯端口
QString DeviceNumber=QString::asprintf("%05d",databuff[11]+databuff[12]*256); //设备自编机号
QString GetWay=QString::asprintf("%d", databuff[13])+"."+QString::asprintf("%d", databuff[14])+"."+QString::asprintf("%d", databuff[15])+"."+QString::asprintf("%d", databuff[16]); //设备网关
QString GetWayMAC=QString::asprintf("%02X", databuff[17])+"-"+QString::asprintf("%02X", databuff[18])+"-"+QString::asprintf("%02X", databuff[19])+"-"+QString::asprintf("%02X", databuff[20])+"-"+QString::asprintf("%02X", databuff[21])+"-"+QString::asprintf("%02X", databuff[22]); //设备网关MAC
QString ServerIp=QString::asprintf("%d", databuff[23])+"."+QString::asprintf("%d", databuff[24])+"."+QString::asprintf("%d", databuff[25])+"."+QString::asprintf("%d", databuff[26]); //远程服务器IP
QString ServerMAC=QString::asprintf("%02X", databuff[27])+"-"+QString::asprintf("%02X", databuff[28])+"-"+QString::asprintf("%02X", databuff[29])+"-"+QString::asprintf("%02X", databuff[30])+"-"+QString::asprintf("%02X", databuff[31])+"-"+QString::asprintf("%02X", databuff[32]); //远程服务器MAC
QString MACPara=QString::asprintf("%d", databuff[33]); //MAC获取方式
QString NetPara=QString::asprintf("%d", databuff[34]); //设备参数
QString ModuleNumber=QString::asprintf("%d", databuff[35])+"-"+QString::asprintf("%d", databuff[36])+"-"+QString::asprintf("%d", databuff[37])+"-"+QString::asprintf("%d", databuff[38]); //网络模块编号
QString STMAC="16-88-"+QString::asprintf("%02X", databuff[35])+"-"+QString::asprintf("%02X", databuff[36])+"-"+QString::asprintf("%02X", databuff[37])+"-"+QString::asprintf("%02X", databuff[38]); //STC版设备MAC
QString CHMAC=""; //CH系列设备MAC
QString SerialNumber=""; //唯一设备硬件序号
for (int i=39;i<buflen;i++){
SerialNumber=SerialNumber+QString::asprintf("%02X", databuff[i]);
if (i<45){
CHMAC=QString::asprintf("%02X", databuff[i])+CHMAC;
if(i<44){CHMAC="-"+CHMAC;}
}
}
int row = 0;
ui->tableWidget->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端口
}
}
}