qt/ledset/mainwin.cpp

324 lines
14 KiB
C++
Raw Normal View History

2022-08-25 18:43:03 +08:00
#include "mainwin.h"
2023-08-21 11:21:00 +08:00
#include "gutil/qjson.h"
2023-03-20 11:30:19 +08:00
#include "pcaprethread.h"
2023-09-01 16:17:33 +08:00
#include "pcap.h"
2022-08-25 18:43:03 +08:00
#include "fast.h"
#include "expertwin.h"
#include "brightwin.h"
2023-06-13 18:00:19 +08:00
#include "testwin.h"
#include "videowin.h"
#include <QLabel>
2022-08-25 18:43:03 +08:00
#include <QPushButton>
#include <QToolButton>
#include <QComboBox>
#include <QMouseEvent>
#include <QPainter>
#include <QPainterPath>
#include <QTimer>
#include <QMessageBox>
2022-12-16 15:08:53 +08:00
#include "globalfunc.h"
#include "basewin.h"
#include <QSettings>
#include <QDir>
#include <QApplication>
2023-05-27 17:43:57 +08:00
#include <QtEndian>
2023-07-28 14:48:41 +08:00
#include <QStandardPaths>
2023-08-21 11:21:00 +08:00
#include <QNetworkDatagram>
#include <QNetworkInterface>
2022-08-25 18:43:03 +08:00
class ImgBtn : public QToolButton {
public:
2022-09-06 23:40:02 +08:00
ImgBtn() {
setStyleSheet("QToolButton{border: none; padding-top: 4px;}");
2022-08-25 18:43:03 +08:00
}
2022-09-06 23:40:02 +08:00
bool isEnter{false};
2022-08-25 18:43:03 +08:00
protected:
2022-09-06 23:40:02 +08:00
void resizeEvent(QResizeEvent *event) override {
QToolButton::resizeEvent(event);
if(isEnter) setIconSize(QSize(width(), width()));
else setIconSize(QSize(width()-8, width()-8));
}
void enterEvent(QEvent *event) override {
QToolButton::enterEvent(event);
2022-08-25 18:43:03 +08:00
setStyleSheet("QToolButton{border: none;}");
setIconSize(QSize(width(), width()));
}
2022-09-06 23:40:02 +08:00
void leaveEvent(QEvent *event) override {
QToolButton::leaveEvent(event);
2022-08-25 18:43:03 +08:00
setIconSize(QSize(width()-8, width()-8));
setStyleSheet("QToolButton{border: none; padding-top: 4px;}");
}
};
inline QLabel *newImgLabel(QPixmap pixmap){
QLabel *lb = new QLabel();
lb->setPixmap(pixmap);
return lb;
}
inline QLabel *newSubLabel(QString txt){
QLabel *lb = new QLabel(txt);
lb->setAlignment(Qt::AlignCenter);
return lb;
}
2022-09-06 23:40:02 +08:00
ImgBtn *addImg(QHBoxLayout *parent, const QIcon &icon, const QString &text) {
auto imgBtn = new ImgBtn();
2023-05-27 17:43:57 +08:00
auto ft = imgBtn->font();
ft.setPixelSize(14);
imgBtn->setFont(ft);
2022-09-06 23:40:02 +08:00
imgBtn->setIcon(icon);
imgBtn->setText(text);
2022-08-25 18:43:03 +08:00
imgBtn->setFixedSize(76, 100);
imgBtn->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
parent->addWidget(imgBtn);
2022-09-06 23:40:02 +08:00
return imgBtn;
2022-08-25 18:43:03 +08:00
}
MainWin::MainWin() {
2022-12-16 15:08:53 +08:00
setWindowTitle("LedSet Express");
2023-05-27 17:43:57 +08:00
resize(900, 600);
auto ft = font();
ft.setPixelSize(14);
setFont(ft);
2022-08-25 18:43:03 +08:00
auto vBox = new QVBoxLayout(center);
vBox->setContentsMargins(0,0,0,0);
vBox->addLayout(addBtns(new QHBoxLayout()));
QHBoxLayout *imgsBar = new QHBoxLayout();
2022-09-06 23:40:02 +08:00
auto btnImg = addImg(imgsBar, QPixmap(":/imgs/fast.png").scaledToWidth(128, Qt::SmoothTransformation), "快速调屏");
2023-06-13 18:00:19 +08:00
connect(btnImg, &ImgBtn::clicked, this, [=] {
2022-08-25 18:43:03 +08:00
(new Fast(this))->show();
});
2022-12-16 15:08:53 +08:00
btnImg = addImg(imgsBar, QPixmap(":/imgs/expert.png").scaledToWidth(128, Qt::SmoothTransformation), tr("专家调屏"));
2023-06-13 18:00:19 +08:00
connect(btnImg, &ImgBtn::clicked, this, [=] {
2023-08-24 16:55:38 +08:00
(new ExpertWin(this, (enum_rcvCardType) table->data(table->currentRow(), "type").toInt()))->show();
2022-08-25 18:43:03 +08:00
});
2022-12-16 15:08:53 +08:00
btnImg = addImg(imgsBar, QPixmap(":/imgs/bright.png").scaledToWidth(128, Qt::SmoothTransformation), tr("亮度控制"));
2023-06-13 18:00:19 +08:00
connect(btnImg, &ImgBtn::clicked, this, [=] {
2022-08-25 18:43:03 +08:00
(new BrightWin(this))->show();
});
2022-12-16 15:08:53 +08:00
btnImg = addImg(imgsBar, QPixmap(":/imgs/correct.png").scaledToWidth(128, Qt::SmoothTransformation), tr("相机矫正"));
2023-06-13 18:00:19 +08:00
connect(btnImg, &ImgBtn::clicked, this, [=] {
2022-08-25 18:43:03 +08:00
});
2022-12-16 15:08:53 +08:00
btnImg = addImg(imgsBar, QPixmap(":/imgs/monitor.png").scaledToWidth(128, Qt::SmoothTransformation), tr("屏体监控"));
2023-06-13 18:00:19 +08:00
connect(btnImg, &ImgBtn::clicked, this, [=] {
2022-08-25 18:43:03 +08:00
});
2022-12-16 15:08:53 +08:00
btnImg = addImg(imgsBar, QPixmap(":/imgs/multi.png").scaledToWidth(128, Qt::SmoothTransformation), tr("多功能卡"));
2023-06-13 18:00:19 +08:00
connect(btnImg, &ImgBtn::clicked, this, [=] {
2022-08-25 18:43:03 +08:00
//win->move(win->x()-1, win->y());
});
2023-06-13 18:00:19 +08:00
btnImg = addImg(imgsBar, QPixmap(":/imgs/test.png").scaledToWidth(128, Qt::SmoothTransformation), tr("协议调试"));
connect(btnImg, &ImgBtn::clicked, this, [=] {
if(reThd->status) return;
(new TestWin(this))->show();
2022-08-25 18:43:03 +08:00
});
2022-12-16 15:08:53 +08:00
btnImg = addImg(imgsBar, QPixmap(":/imgs/idea.png").scaledToWidth(128, Qt::SmoothTransformation), tr("模拟同步"));
2023-06-13 18:00:19 +08:00
connect(btnImg, &ImgBtn::clicked, this, [=] {
2022-12-16 15:08:53 +08:00
auto ins = VideoWin::newIns(net_name, this);
if(ins) ins->show();
2022-08-25 18:43:03 +08:00
});
vBox->addLayout(imgsBar);
2022-12-16 15:08:53 +08:00
vBox->addSpacing(9);
2022-08-25 18:43:03 +08:00
vBox->addWidget(new QLabel(" 硬件信息"));
2022-12-16 15:08:53 +08:00
table = new Table{
2023-08-24 16:55:38 +08:00
{"type", "控制系统类型"},
2022-12-16 15:08:53 +08:00
{"name", "名称"},
{"link", "连接方式"},
2023-05-27 17:43:57 +08:00
{"vcsNum", "接收卡数量"},
{"netPorts", "网口统计P1~Pn"},
{"info", "其他信息", QHeaderView::Stretch},
2022-12-16 15:08:53 +08:00
};
2023-08-24 16:55:38 +08:00
table->verticalHeader()->setMinimumWidth(20);//added by alahover 20230822
2023-05-27 17:43:57 +08:00
table->setDefs();
2022-12-16 15:08:53 +08:00
vBox->addWidget(table);
2023-08-21 11:21:00 +08:00
auto hBox = new HBox(vBox);
hBox->addLabel("V" __VER__" - " __DATE__);
hBox->addStretch();
2022-08-25 18:43:03 +08:00
2022-12-16 15:08:53 +08:00
auto btnNetSelect = new QPushButton("通讯选择");
connect(btnNetSelect, &QPushButton::clicked, this, [this] {
2023-03-24 18:41:48 +08:00
auto name = getNetDev(this, net_name, false);
2022-12-16 15:08:53 +08:00
if(name.isEmpty()) return;
//PCAP_OPENFLAG_DATATX_UDP2它定义了数据传输假如是远程抓包是否用UDP协议来处理。
//PCAP_OPENFLAG_NOCAPTURE_RPCAP4它定义了远程探测器是否捕获它自己产生的数据包。
2023-06-13 18:00:19 +08:00
char errbuf[PCAP_ERRBUF_SIZE]{0};
2022-12-16 15:08:53 +08:00
auto pcapR = pcap_open_live(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS|4|8|16, 50, errbuf);
if(pcapR == 0) {
QMessageBox::critical(this, "Error", QString(tr("打开网卡失败"))+errbuf);
return;
}
auto pcapS = pcap_open_live(name.data(), 65536, 0, 50, errbuf);
if(pcapS == 0) {
QMessageBox::critical(this, "Error", QString(tr("打开网卡失败"))+errbuf);
return;
}
2023-03-20 11:30:19 +08:00
if(reThd) reThd->status = 2;
2022-12-16 15:08:53 +08:00
if(pcapSend) pcap_close(pcapSend);
pcapSend = pcapS;
2023-03-20 11:30:19 +08:00
reThd = new PcapReThread(pcapR);
reThd->start();
2023-06-07 19:11:03 +08:00
QSettings().setValue("net_name", net_name = name);
2022-12-16 15:08:53 +08:00
});
2023-08-21 11:21:00 +08:00
hBox->addWidget(btnNetSelect);
2022-12-16 15:08:53 +08:00
auto btnRefresh = new QPushButton(tr("刷新"));
2023-03-20 12:11:58 +08:00
connect(btnRefresh, &QPushButton::clicked, this, &MainWin::getCard);
2023-08-21 11:21:00 +08:00
hBox->addWidget(btnRefresh);
2022-12-16 15:08:53 +08:00
2023-06-06 12:13:33 +08:00
show();
2023-06-07 19:11:03 +08:00
QSettings config;
2023-07-28 14:48:41 +08:00
gFileHome = config.value("FileHome").toString();
if(gFileHome.isEmpty() || ! QFileInfo(gFileHome).isDir()) gFileHome = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
2022-12-16 15:08:53 +08:00
auto name = config.value("net_name").toByteArray();
2023-03-24 18:41:48 +08:00
name = getNetDev(this, name, true);
2022-12-16 15:08:53 +08:00
if(! name.isEmpty()) {
2023-06-13 18:00:19 +08:00
char errbuf[PCAP_ERRBUF_SIZE]{0};
2023-03-20 11:30:19 +08:00
auto pcapRe = pcap_open_live(name.data(), 65536, PCAP_OPENFLAG_PROMISCUOUS|4|8|16, 50, errbuf);
2022-12-16 15:08:53 +08:00
if(pcapRe == 0) QMessageBox::critical(this, "Error", QString(tr("打开网卡失败"))+errbuf);
else {
pcapSend = pcap_open_live(name.data(), 65536, 0, 50, errbuf);
if(pcapSend == 0) QMessageBox::critical(this, "Error", QString(tr("打开网卡失败"))+errbuf);
2023-03-20 11:30:19 +08:00
else {
config.setValue("net_name", net_name = name);
reThd = new PcapReThread(pcapRe);
reThd->start();
}
2022-12-16 15:08:53 +08:00
}
}
2023-08-21 11:21:00 +08:00
connect(&mUdpSocket, &QUdpSocket::readyRead, this, [this] {
while(mUdpSocket.hasPendingDatagrams()) {
auto gram = mUdpSocket.receiveDatagram();
auto data = gram.data();
if(data.isEmpty()) continue;
auto senderAddress = gram.senderAddress();
bool ok = true;
if(senderAddress.protocol()==QUdpSocket::IPv6Protocol) senderAddress.setAddress(senderAddress.toIPv4Address(&ok));
auto addr = ok ? senderAddress.toString() : "";
int cnt = table->rowCount();
if(data.startsWith("{\"")) {
QString error;
auto json = JFrom(gram.data(), &error);
if(! error.isEmpty()) {
qDebug()<<"Json Error: "+error;
continue;
}
auto cardId = json["cardId"].toStr();
for(int rr=0; rr<cnt; rr++) if(table->text(rr, "name")==cardId) {
table->setText(rr, "link", addr);
goto end;
}
table->setRowCount(cnt+1);
2023-08-24 16:55:38 +08:00
table->setData(cnt, "type", enum_xixun_async)->setText(tr("异步卡"));//added by alahover 20230822
2023-08-21 11:21:00 +08:00
table->setText(cnt, "name", cardId);
table->setText(cnt, "link", addr);
} else {
auto bytes = gram.data();
auto packet = (UDPPacket *)bytes.data();
for(int rr=0; rr<cnt; rr++) if(table->text(rr, "name")==packet->serialCode) {
table->setText(rr, "link", addr);
goto end;
}
table->setRowCount(cnt+1);
2023-08-24 16:55:38 +08:00
table->setData(cnt, "type", enum_xixun_async)->setText(tr("异步卡"));
2023-08-21 11:21:00 +08:00
table->setText(cnt, "name", packet->serialCode);
table->setText(cnt, "link", addr);
}
end:;
}
});
2023-09-01 16:17:33 +08:00
reThd->addMultiCallback(0x105B14, [=](int, const QByteArray data) {
auto rr = table->rowCount();
unsigned short ver = *(quint16_be *)(data.data()+headMap_zrf.protcolFlag);
unsigned char pkgType = *(quint8 *)(data.data()+headMap_zrf.pkgType);
if(ver!=0x105B || pkgType != 0x14) return;
2023-09-01 17:25:53 +08:00
auto strDeviceName = QString(QLatin1String(data.data()+headMap_zrf.paramStart+st_zrf_rb_param.deviceName, 9));
for(int i=0;i<rr;i++) if(table->text(i,1)==strDeviceName) {
rr = i;
goto end;
}
table->setRowCount(rr+1);
end:
char cDevicaNameVer[8];
memcpy(cDevicaNameVer,(char *)data.data()+headMap_zrf.paramStart+st_zrf_rb_param.deviceVer,8);
QString strDeviceVer = QString(QLatin1String(cDevicaNameVer));
strDeviceVer=strDeviceVer.left(8);
int virtualVCM = *(quint8*)(data.data()+headMap_zrf.netPort)+1;
int rcvIdex = *(quint8*)(data.data()+headMap_zrf.rcvIndex)+1;
if(rcvIdex > maxNetPort_zrf) maxNetPort_zrf = rcvIdex;
2023-09-01 16:17:33 +08:00
table->setData(rr, "type", enum_zrf)->setText(tr("PC虚拟卡V1.0"));
2023-09-01 17:25:53 +08:00
table->setText(rr, "name", strDeviceName);
2023-09-01 16:17:33 +08:00
table->setText(rr, "link", "千兆网直连");
2023-09-01 17:25:53 +08:00
table->setText(rr, "vcsNum", QString::number(maxNetPort_zrf));
2023-09-01 16:17:33 +08:00
table->setText(rr, "netPorts", "P:"+QString::number(virtualVCM));
2023-09-01 17:25:53 +08:00
table->setText(rr, "info", "版本: "+strDeviceVer+" [备注:可直接配屏,无需发送卡]");
if(rr==0) table->selectRow(0);
2023-09-01 16:17:33 +08:00
});
2023-03-20 12:11:58 +08:00
getCard();
}
2023-07-28 14:48:41 +08:00
MainWin::~MainWin() {
2023-08-21 11:21:00 +08:00
mUdpSocket.close();
2023-07-28 14:48:41 +08:00
QSettings config;
config.setValue("FileHome", gFileHome);
}
2022-12-16 15:08:53 +08:00
2023-03-20 12:11:58 +08:00
void MainWin::getCard() {
2023-05-27 17:43:57 +08:00
table->setRowCount(0);
auto msg = QByteArray::fromHex("5555 01 0D 0008 FFFFFFFF 0000ABCD A0000000 0000 38CB847E 00000000 0000ABCD CD040446");
2023-06-06 12:13:33 +08:00
auto res = sendMsg(msg, 0x1E0, 10000, [=](int, const QByteArray data) {
2023-05-27 17:43:57 +08:00
if(*(quint32_be*)(data.data()+headMap.ptr) != 0xA0000000) return;
2023-08-24 16:55:38 +08:00
auto rr = table->rowCount();
2023-05-27 17:43:57 +08:00
table->setRowCount(rr+1);
int virtualVCM = *(quint16_be*)(data.data()+headMap.srcAddr);
2023-08-24 16:55:38 +08:00
//modified by alahover -s 20230822
auto ver = *(byte*)(data.data()+headMap.ver);
2023-09-01 16:17:33 +08:00
if(ver==0x01) table->setData(rr, "type", enum_xixun_sync)->setText(tr("PC虚拟卡V0.0"));
else if(ver==0x58) table->setData(rr, "type", enum_zrf)->setText(tr("PC虚拟卡V1.0"));
2023-05-27 17:43:57 +08:00
table->setText(rr, "name", tr("网口:")+QString::number(virtualVCM));
table->setText(rr, "link", "千兆网直连");
table->setText(rr, "vcsNum", QString::number(*(quint32_be*)(data.data()+headMap.body)));
table->setText(rr, "netPorts", "P:"+QString::number(virtualVCM));
table->setText(rr, "info", "备注:可直接配屏,无需发送卡");
2023-06-06 12:13:33 +08:00
});
2023-08-21 11:21:00 +08:00
if(res) {
QString err = pcap_geterr(pcapSend);
if(! err.endsWith("(2150891551)")) QMessageBox::critical(this, "Error", QString(tr("发送失败: "))+QString::fromLocal8Bit(pcap_geterr(pcapSend)));
}
2023-08-24 16:55:38 +08:00
//modified by alahover -s 20230822
2023-09-01 17:25:53 +08:00
//查询105B协议类型ZRF版本fpga的接收卡, 0x105B1400 表示是zrf协议类型并且是回读数据包
msg = QByteArray::fromHex("5555 001122334455 001122334455 105A 13 00 00 00 00 e0 ff ff 00 f2 f2 f2 f2 00 00 00 00 00 00 00 00 00 00 00 00");
2023-09-01 16:17:33 +08:00
res = pcap_sendpacket(pcapSend, (const u_char *)msg.data(), msg.size());
2023-08-24 16:55:38 +08:00
if(res) {
QString err = pcap_geterr(pcapSend);
if(! err.endsWith("(2150891551)")) QMessageBox::critical(this, "Error", QString(tr("发送失败: "))+QString::fromLocal8Bit(pcap_geterr(pcapSend)));
}
2023-08-21 11:21:00 +08:00
auto data = JToBytes(JObj{{"action", "getInfo"}});
uchar ccc[]{0x7E, 0x7E, 0x7E, 0x90, 0x42, 0x72, 0x6F, 0x61, 0x64, 0x63, 0x61, 0x73, 0x74, 0x21,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x1C, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x9F};
if(mUdpSocket.writeDatagram(data, QHostAddress("255.255.255.255"), 22222) != data.length()) qDebug() << "getInfo write to 255.255.255.255 failed";
if(mUdpSocket.writeDatagram((char *)ccc, sizeof(ccc), QHostAddress("255.255.255.255"), 31296) != sizeof(ccc)) qDebug() << "getInfo write to 255.255.255.255 failed";
auto networkinterfaces = QNetworkInterface::allInterfaces();
foreach(auto face, networkinterfaces) {
auto flags = face.flags();
bool can = (flags & QNetworkInterface::IsRunning) && (flags & QNetworkInterface::CanBroadcast) && ! (flags & QNetworkInterface::IsLoopBack);
if(! can) continue;
auto addrEntries = face.addressEntries();
foreach(QNetworkAddressEntry addrEntry, addrEntries) {
auto ip = addrEntry.ip();
if(ip.protocol()!=QAbstractSocket::IPv4Protocol) continue;
auto broadcast = addrEntry.broadcast();
if(mUdpSocket.writeDatagram(data, broadcast, 22222) != data.length()) qDebug() << "getInfo write failed." << ip.toString() << "->" << broadcast.toString();
}
}
2022-12-16 15:08:53 +08:00
}