qt/LedOK/program/sendprogthread.cpp
2024-06-19 18:54:32 +08:00

206 lines
7.2 KiB
C++

#include "sendprogthread.h"
#include "gutil/qnetwork.h"
#include <QHostAddress>
#include <QDir>
#include <QDirIterator>
#include <QMessageBox>
#include <QMetaEnum>
SendProgThread::SendProgThread(const QString &progDir, const QString &ip, int port) : prog_dir(progDir), ip(ip), port(port) {
connect(this, &QThread::finished, this, &QThread::deleteLater);
}
void SendProgThread::run() {
emit emProgress(0); // 进度条归零
auto fileNames = QDir(prog_dir).entryList(QDir::Files);
if(fileNames.isEmpty()) {
emit emErr(tr("Program is empty"));
return;
}
if(stoped) return;
TcpSocket tcp;
tcp.connectToHost(ip, port);
if(! tcp.waitForConnected()) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at waitForConnected");
tcp.close();
return;
}
if(stoped) {
tcp.close();
return;
};
//发送节目列表协商
JArray files;
for(auto &name : fileNames) if(name!="program") {
QFileInfo info(prog_dir+"/"+name);
files.append(JObj{{"name", info.baseName()}, {"size", info.size()}});
}
if(! files.empty()) {
JObj req;
req.insert("_type", "consult");
req.insert("files", files);
req.insert("idList", JArray{"aaa"});
req.insert("zVer", "xixun1");
auto resNum = tcp.write(JToBytes(req));
tcp.flush();
if(resNum == -1 || ! tcp.waitForBytesWritten() || ! tcp.waitForReadyRead()) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at waitForRead 'checkExist'");
tcp.close();
return;
}
auto resp = tcp.readAll();
QString error;
auto res = JFrom(resp, &error);
while(error.contains("end-of-input")) {
if(! tcp.waitForReadyRead()) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at waitForRead2 'checkExist'");
tcp.close();
return;
}
resp += tcp.readAll();
error = "";
res = JFrom(resp, &error);
}
if(! error.isEmpty()) {
emit emErr(error+" at parse 'checkExist'");
tcp.close();
return;
}
auto existeds = res["existed"].toArray();
for(auto &existed : existeds) fileNames.removeAll(existed.toString());
}
if(stoped) {
tcp.close();
return;
}
qint64 progSize = 0;
for(auto &name : fileNames) progSize += QFileInfo(prog_dir+"/"+name).size();
if(progSize == 0) {
emit emErr(tr("Program is empty"));
tcp.close();
return;
}
auto req = JObj();
req.insert("_type", "proStart");
req.insert("proName", "program");
req.insert("proSize", progSize);
req.insert("zVer","xixun1");
auto resNum = tcp.write(JToBytes(req));
tcp.flush();
if(resNum == -1 || ! tcp.waitForBytesWritten()) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at write 'proStart'");
tcp.close();
return;
}
if(stoped) {
tcp.close();
return;
}
//4.发送协商列表应答里的文件
int64_t sentBytes = 0;
char buf[8192];
for(auto &name : fileNames) {
QFileInfo info(prog_dir+"/"+name);
auto baseName = info.baseName();
auto remain = info.size();
req = JObj();
req.insert("_type", "fileStart");
req.insert("id", baseName);
req.insert("size", remain);
req.insert("zVer","xixun1");
auto resNum = tcp.write(JToBytes(req));
if(resNum == -1) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at write 'fileStart'");
tcp.close();
return;
}
auto file = new QFile(info.filePath());
if(! file->open(QFile::ReadOnly)) {
emit emErr(tr("Open file failed")+" "+file->errorString());
tcp.close();
return;
}
while(remain > 0) {
resNum = file->read(buf, qMin(8192LL, remain));
if(resNum <= 0) {
emit emErr(tr("Read file failed")+" "+file->errorString());
tcp.close();
file->close();
return;
}
if(stoped) {
tcp.close();
file->close();
return;
};
if(! tcp.waitForBytesWritten(60000)) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at waitForWritten file: "+file->fileName());
tcp.close();
file->close();
return;
}
resNum = tcp.write(buf, resNum);
if(resNum <= 0) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at write file: "+file->fileName());
tcp.close();
file->close();
return;
}
if(stoped) {
tcp.close();
file->close();
return;
};
remain -= resNum;
sentBytes += resNum;
if(sentBytes != 0) emit emProgress(sentBytes * 99 / progSize);
}
file->close();
if(stoped) {
tcp.close();
return;
};
req = JObj();
req.insert("_type", "fileEnd");
req.insert("id", baseName);
req.insert("zVer", "xixun1");
resNum = tcp.write(JToBytes(req));
tcp.flush();
if(resNum == -1 || ! tcp.waitForBytesWritten()) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at write 'fileEnd'");
tcp.close();
return;
}
}
if(stoped) {
tcp.close();
return;
};
//5.发送结束
req = JObj();
req.insert("_type", "proEnd");
req.insert("proName", "program");
req.insert("zVer","xixun1");
resNum = tcp.write(JToBytes(req));
tcp.flush();
if(resNum == -1 || ! tcp.waitForBytesWritten()) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at write 'proEnd'");
tcp.close();
return;
};
if(! tcp.waitForReadyRead()) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at waitForRead 'proEnd'");
tcp.close();
return;
}
auto resp = tcp.readAll();
if(resp.isEmpty()) {
emit emErr(QString(socketErrKey(tcp.error()))+" ("+QString::number(tcp.error())+") "+tcp.errorString()+" at read 'proEnd'");
tcp.close();
return;
}
tcp.close();
emit emProgress(100);
emit emErr("OK");
}