#include "devicepanel.h" #include "devicectrlpanel.h" #include "tools.h" #include "gutil/qgui.h" #include #include #include #include #include #include #include #include DevicePanel *gDevicePanel; QList *gSelCards; //设备管理响应页面 DevicePanel::DevicePanel(QSettings &settings, QWidget *parent) : QWidget(parent) { gDevicePanel = this; gSelCards = &mSelCards; setAutoFillBackground(true); QPalette pal; pal.setBrush(QPalette::Window, QColor(0xeeeeee)); setPalette(pal); auto vBox = new VBox(this); vBox->setContentsMargins(0, 0, 0, 0); vBox->setSpacing(0); auto hBox = new HBox(vBox); hBox->setContentsMargins(6, 2, 6, 2); hBox->setSpacing(2); auto label = new QLabel(); label->setPixmap({":/res/device/DeviceNum_All.png"}); label->setScaledContents(true); label->setFixedSize(33, 24); hBox->addWidget(label); label_3 = new QLabel(tr("All")); hBox->addWidget(label_3); nDeviceNum = new QLabel(); nDeviceNum->setFixedSize(40, 20); hBox->addWidget(nDeviceNum); auto fdSearch = new QLineEdit(); fdSearch->setClearButtonEnabled(true); fdSearch->setFixedSize(220, 30); fdSearch->addAction(new QAction(QIcon(":/res/program/bnSearch.png"), QString()), QLineEdit::LeadingPosition); fdSearch->setStyleSheet("border: 1px solid #aaaaaa;"); connect(fdSearch, &QLineEdit::textChanged, this, [this](const QString &search) { auto cnt = mDeviceTable->topLevelItemCount(); if(search.isEmpty()) for(int i=0; itopLevelItem(i)->setHidden(false); else for(int i=0; itopLevelItem(i); item->setHidden(! (item->text(DeviceTable_ID).contains(search) || item->text(DeviceTable_Remark).contains(search) || item->text(DeviceTable_IP).contains(search))); } }); hBox->addWidget(fdSearch); hBox->addSpacing(10); fdCardNumInfo = new QLabel(tr("Current Screen")+": "+tr("none")); fdCardNumInfo->setStyleSheet("QLabel{color: #15f;}"); fdCardNumInfo->hide(); hBox->addWidget(fdCardNumInfo); hBox->addStretch(); auto areaFlash = new QWidget(); areaFlash->setFixedSize(100, 34); bnSpecifyIP = new QComboBox(areaFlash); bnSpecifyIP->addItem(tr("Specify IP")); bnSpecifyIP->setGeometry(0, 0, areaFlash->width(), areaFlash->height()); bnSpecifyIP->setItemDelegate(new QStyledItemDelegate); connect(bnSpecifyIP, &QComboBox::textActivated, this, [this] { mUdpTimer.stop(); specifyIPDlg->exec(); mUdpTimer.start(30000); }); bnSpecifyIP->setStyleSheet(R"rrr( QComboBox { border: none; border-radius: 5px; background-color: #19c; } QComboBox:hover {background-color: #08b;} QComboBox::drop-down {width: 25px;} QComboBox::down-arrow {image: url(:/res/device/FlashArrow.png);} QComboBox QAbstractItemView::item { height: 28px; color: #fff; } QComboBox QAbstractItemView::item:selected {background-color: #09c;} )rrr"); btnRefresh = new QPushButton(tr("Refresh"), areaFlash); btnRefresh->setGeometry(0, 0, 75, areaFlash->height()); connect(btnRefresh, &QPushButton::clicked, this, [this] { mLedCards.clear(); mDeviceTable->onCheckAll(false); mDeviceTable->clear(); nDeviceNum->setText("0"); sendGetInfo(); }); btnRefresh->setStyleSheet(R"rrr( QPushButton { border-radius: 5px; background-color: #19c; color: #fff; } QPushButton:hover {background-color: #08b;} )rrr"); hBox->addWidget(areaFlash); mHBox = new QHBoxLayout(); mDeviceTable = new LoQTreeWidget(this); mDeviceTable->setIndentation(0); mDeviceTable->setSortingEnabled(true); mHBox->addWidget(mDeviceTable); vBox->addLayout(mHBox); connect(&mUdpTimer, &QTimer::timeout, this, &DevicePanel::sendGetInfo); 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() : ""; if(data.startsWith("{\"")) { QJsonParseError error; QJsonDocument document = QJsonDocument::fromJson(gram.data(), &error); if(error.error != QJsonParseError::NoError) { qDebug()<<"DeviceItem OnProHttpResponse 解析json文件错误!"; continue; } parseInfo(document.object(), addr); } else { auto bytes = gram.data(); auto packet = (Packet *)bytes.data(); LedCard *pLedCard = new LedCard(this);//alahover 没有释放 pLedCard->m_strCardId = packet->serialCode; pLedCard->m_strCardIp = addr; for(int i=0;im_strCardId==pLedCard->m_strCardId ) {//如果已经存在在列表中 auto pOldLedCard = mLedCards.at(i);//获取到旧的对象指针 pOldLedCard->m_bOnLine = true; if(pOldLedCard->CompareHTTPGetParam(pLedCard)==false) {//如果ip地址变化了 pOldLedCard->copyLedCardHTTPGetParam(pLedCard); addLedCard(pOldLedCard);//发送信号到界面 } else { //post失败的概率比较小,所以这里是否需要平凡的更新,不需要刻意屏蔽该操作改为在其他点击操作中进行 clearUdpHeartbeat(pOldLedCard); } delete pLedCard; return; } mLedCards.append(pLedCard); addLedCard(pLedCard);//发送信号到界面 } } }); m_headerItem = new QTreeWidgetItem(); for(int i=1; isetTextAlignment(i, Qt::AlignCenter); mDeviceTable->setHeaderItem(m_headerItem); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Check, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_Check, 36); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Online, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_Online, 48); mDeviceTable->header()->setSectionResizeMode(DeviceTable_ID, QHeaderView::Stretch); mDeviceTable->header()->setSectionResizeMode(DeviceTable_IP, QHeaderView::Stretch); mDeviceTable->header()->setSectionResizeMode(DeviceTable_ScreenSize, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_ScreenSize, 108); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Remark, QHeaderView::Stretch); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Brightness, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_Brightness, 108); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Power, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_Power, 84); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Password, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_Password, 72); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Info, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_Info, 72); mDeviceTable->header()->setSectionResizeMode(DeviceTable_Screenshot, QHeaderView::Fixed); mDeviceTable->setColumnWidth(DeviceTable_Screenshot, 72); connect(mDeviceTable, SIGNAL(sigCheckStateChanged(int)), this, SLOT(onCheckStateChanged(int))); mDeviceTable->setSelectionMode(QAbstractItemView::SingleSelection); mDeviceTable->hideColumn(0); mDeviceTable->fdIsSelAll->hide(); specifyIPDlg = new QDialog(this); specifyIPDlg->setWindowTitle(tr("Specify IP")); vBox = new VBox(specifyIPDlg); vBox->addStretch(); label = new QLabel(tr("Specify IP list")); label->setAlignment(Qt::AlignCenter); vBox->addWidget(label); fdIP = new QTextEdit; auto ipstr = settings.value("SpecifyIP").toString(); if(! ipstr.isEmpty()) fdIP->setText(ipstr); fdIP->setPlaceholderText("192.168.1.1\n192.168.1.2\n ..."); fdIP->setMinimumWidth(160); vBox->addWidget(fdIP); hBox = new HBox(vBox); hBox->addStretch(); auto bnSearch = new QPushButton(tr("Search")); connect(bnSearch, &QPushButton::clicked, this, [this] { QString ipsStr = fdIP->toPlainText(); if(ipsStr.isEmpty()) { QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input IP address!")); return; } auto ips = ipsStr.split("\n", Qt::SkipEmptyParts); if(ips.isEmpty()) { QMessageBox::warning(gMainWin, tr("Attention"), tr("Please input IP address!")); return; } QByteArray data = QJsonDocument({{"action", "getInfo"}}).toJson(QJsonDocument::Compact); foreach(auto ip, ips) { if(gDevicePanel->mUdpSocket.writeDatagram(data, QHostAddress(ip), 22222) != data.length()) qDebug() << "Specify IP write Failed." << ip; } specifyIPDlg->accept(); }); hBox->addWidget(bnSearch); auto btnCancel = new QPushButton(tr("Cancel")); connect(btnCancel, &QPushButton::clicked, specifyIPDlg, &QDialog::reject); hBox->addWidget(btnCancel); hBox->addStretch(); transUi(); sendGetInfo(); mUdpTimer.start(30000); } DevicePanel::~DevicePanel() { mUdpSocket.close(); mUdpTimer.stop(); } void DevicePanel::sendGetInfo() { const QByteArray data = QJsonDocument({{"action", "getInfo"}}).toJson(QJsonDocument::Compact); 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"; QList networkinterfaces = QNetworkInterface::allInterfaces(); foreach(QNetworkInterface 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(); } } auto ipstr = fdIP->toPlainText(); if(! ipstr.isEmpty()) { auto ips = ipstr.split("\n", Qt::SkipEmptyParts); foreach(auto ip, ips) if(mUdpSocket.writeDatagram(data, QHostAddress(ip), 22222) != data.length()) qDebug() << "getInfo specify IP write failed." << ip; } } void DevicePanel::ShowDevicesInfoOrControlWidget(int index){ m_intIndexFlagOfInfoOrControl=index; if(index==MainPage_DeviceManager) { //设备信息列表页面 mDeviceTable->hideColumn(0); mDeviceTable->fdIsSelAll->hide(); if(mDeviceCtrlPanel!=nullptr) { for(int j=DeviceTable_ScreenSize;jshowColumn(j); mDeviceTable->setMaximumWidth(0xffffff); mDeviceCtrlPanel->hide(); fdCardNumInfo->hide(); } } else if(index==MainPage_Setting) { //终端控制页面 mDeviceTable->showColumn(0); mDeviceTable->fdIsSelAll->show(); for(int j=DeviceTable_ScreenSize; jhideColumn(j); if(mDeviceCtrlPanel==nullptr) mHBox->addWidget(mDeviceCtrlPanel = new DeviceCtrlPanel(this)); else mDeviceCtrlPanel->show(); fdCardNumInfo->show(); mDeviceTable->setMaximumWidth(340); GetSelectDeviceNum(); emit sigSelectedDeviceList(&mSelCards); } int cnt = mDeviceTable->topLevelItemCount(); if(cnt>0)//切换到终点管理页面是刷新列表中控制卡的状态参数 for(int i=0; i(mDeviceTable->topLevelItem(i))->SetMainTabWidgetIndex(m_intIndexFlagOfInfoOrControl); } void DevicePanel::changeEvent(QEvent *event) { QWidget::changeEvent(event); if(event->type() == QEvent::LanguageChange) transUi(); } void DevicePanel::transUi() { btnRefresh->setText(tr("Refresh")); bnSpecifyIP->setItemText(0,tr("Specify IP")); label_3->setText(tr("All")); m_headerItem->setText(DeviceTable_Online, tr("Online")); m_headerItem->setText(DeviceTable_ID, tr("Screen ID")); m_headerItem->setText(DeviceTable_IP, tr("Screen IP")); m_headerItem->setText(DeviceTable_ScreenSize, tr("Screen Size")); m_headerItem->setText(DeviceTable_Remark, tr("Remark Name")); m_headerItem->setText(DeviceTable_Screenshot, tr("readback pic")); m_headerItem->setText(DeviceTable_Brightness, tr("Cur Brightness")); m_headerItem->setText(DeviceTable_Power, tr("Power Status")); m_headerItem->setText(DeviceTable_Password, tr("Security")); m_headerItem->setText(DeviceTable_Info, tr("More Info")); auto cnt = mDeviceTable->topLevelItemCount(); for(int i=0; i(mDeviceTable->topLevelItem(i))->refreshLable(); } void DevicePanel::OnControlTcpSend(int iProgramIndex){ int cnt = mDeviceTable->topLevelItemCount(); for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) static_cast(mDeviceTable->topLevelItem(i))->OnControlTcpSend(iProgramIndex); } void DevicePanel::OnControlSendJson(QJsonObject &json,QString strFanYi){ int cnt = mDeviceTable->topLevelItemCount(); for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { DeviceItem *item = static_cast(mDeviceTable->topLevelItem(i)); item->HttpPostByTypeJsonObject(json); QString strCardId=item->mCard->m_strCardId; mDeviceCtrlPanel->OnOutputInfo(strCardId+":"+tr("send")+"->"+strFanYi); } } int DevicePanel::GetSelectDeviceNum() { int cnt = mDeviceTable->topLevelItemCount(); int iSelectCount=0; mSelCards.clear(); for(int i=0; itopLevelItem(i)->checkState(0) == Qt::Checked) { iSelectCount++; mSelCards.append(static_cast(mDeviceTable->topLevelItem(i))->mCard); } return iSelectCount; } void DevicePanel::OnOutputInfo(QString strInfo) { if(m_intIndexFlagOfInfoOrControl==MainPage_Setting && mDeviceCtrlPanel!=nullptr) mDeviceCtrlPanel->OnOutputInfo(strInfo); } void DevicePanel::onCheckStateChanged(int f){ Q_UNUSED(f); if(m_intIndexFlagOfInfoOrControl==MainPage_Setting){ GetSelectDeviceNum(); emit sigSelectedDeviceList(&mSelCards); } } void DevicePanel::addLedCard(LedCard *card) { int cnt = mDeviceTable->topLevelItemCount(); for(int i=0; i(mDeviceTable->topLevelItem(i)); if(item->mCard->m_strCardId != card->m_strCardId) continue; item->setData(DeviceTable_ID, 0, card->m_strCardId); item->setData(DeviceTable_IP, 0, card->m_strCardIp); item->setData(DeviceTable_ScreenSize, 0, QString("%1 x %2").arg(card->m_iWidth).arg(card->m_iHeight)); return; } new DeviceItem(card, mDeviceTable, this); nDeviceNum->setText(QString::number(mDeviceTable->topLevelItemCount())); QJsonObject json; json.insert("_id", "SyncTime"); json.insert("_type", "SyncTime"); json.insert("time", QDateTime::currentDateTime().toMSecsSinceEpoch()); auto reply = NetReq("http://"+card->m_strCardIp+":2016/settings").timeout(120000).post(json); connect(reply, &QNetworkReply::finished, reply, &QNetworkReply::deleteLater); } void DevicePanel::clearUdpHeartbeat(LedCard *p) { int cnt = mDeviceTable->topLevelItemCount(); for(int i=0; i(mDeviceTable->topLevelItem(i)); if(item->mCard->m_strCardId != p->m_strCardId) continue; item->m_HeartbeatCount = 0; if(item->m_ImageOnline) { item->mCard->m_bOnLine = true; item->m_ImageOnline->setPixmap(QPixmap(":/res/device/O_Online.png")); } return; } } void DevicePanel::parseInfo(const QJsonObject &subObj, const QString &strIp) { LedCard *pLedCard = new LedCard(this);//alahover 没有释放 pLedCard->m_strCardId=subObj["cardId"].toString(); if(! strIp.isEmpty()) pLedCard->m_strCardIp = strIp; else { pLedCard->m_strCardIp = subObj["newIp"].toString(); if(pLedCard->m_strCardIp.isEmpty()) pLedCard->m_strCardIp = subObj["ip"].toString(); } pLedCard->m_iWidth=subObj["width"].toInt(); pLedCard->m_iHeight=subObj["height"].toInt(); pLedCard->starterversionName=subObj["versionName"].toString(); pLedCard->starterPort=subObj["starterPort"].toInt(); pLedCard->androidVersion=subObj["androidVersion"].toString(); pLedCard->iHttpGetId=subObj["id"].toInt(); pLedCard->androidHeight=subObj["androidHeight"].toInt(); pLedCard->androidWidth=subObj["androidWidth"].toInt(); pLedCard->lastActive=subObj["lastActive"].toInt(); for(int i=0;im_strCardId==pLedCard->m_strCardId ) { //如果已经存在在列表中 auto pOldLedCard = mLedCards.at(i);//获取到旧的对象指针 pOldLedCard->m_bOnLine = true; if(! pOldLedCard->CompareHTTPGetParam(pLedCard)) {//如果ip地址变化了 pOldLedCard->copyLedCardHTTPGetParam(pLedCard); addLedCard(pOldLedCard);//发送信号到界面 } else { //post失败的概率比较小,所以这里是否需要平凡的更新,不需要刻意屏蔽该操作改为在其他点击操作中进行 clearUdpHeartbeat(pOldLedCard); } delete pLedCard; return; } mLedCards.append(pLedCard); addLedCard(pLedCard);//发送信号到界面 } STREAM_PACKET LedOkMakeStreamPacket(int iComType,int iLen,unsigned char *ucBuf,QString str) { STREAM_PACKET Temp; memset(&Temp, 0, sizeof(STREAM_PACKET)); if(iLen>2048) return Temp; memset(Temp.SyncHead, 0x7e, 3); memset(Temp.ucSerialCode,0x00,20); char* ch; QByteArray ba = str.toLatin1(); // must ch=ba.data(); memcpy(Temp.ucSerialCode,ch,ba.size()); Temp.iLength=iLen; Temp.ucCommType=iComType; memcpy(Temp.pDataBuffer,ucBuf,iLen); Temp.pDataBuffer[Temp.iLength] = GetCheckCodeIn8(&Temp.ucCommType,Temp.iLength+sizeof(Temp.ucCommType)+sizeof(char)*20+sizeof(Temp.iLength)); return Temp; } //UDP多网卡广播 void DevicePanel::RestoreLedCardIpByUdpCmd() { QList networkinterfaces = QNetworkInterface::allInterfaces(); foreach (QNetworkInterface interfaces, networkinterfaces) {//networkinterfaces负责提供主机的IP地址和网络接口的列表 foreach (QNetworkAddressEntry entry, interfaces.addressEntries()) {//QNetworkAddressEntry存储了一个IP地址,子网掩码和广播地址 entry.setBroadcast(QHostAddress::Broadcast); QHostAddress broadcastAddress("255.255.255.255"); entry.setBroadcast(QHostAddress::Broadcast); RESTORE_IP stTempIp; memset(&stTempIp,0x00,sizeof(RESTORE_IP)); QString strNew=entry.ip().toString(); int itempOffset = strNew.lastIndexOf("."); QString sstrNew=strNew.left(itempOffset)+".254"; if(sstrNew.length()<=20) memcpy(stTempIp.cNewIp,sstrNew.toLatin1().data(),sstrNew.length()); QString strMask=entry.netmask().toString(); if(strMask.length()<=20) memcpy(stTempIp.cMask,strMask.toLatin1().data(),strMask.length()); QString strGateway=entry.ip().toString(); if(strGateway.length()<=20) memcpy(stTempIp.cGateway,strGateway.toLatin1().data(),strGateway.length()); if(strGateway.length()<=20) memcpy(stTempIp.cDns,strGateway.toLatin1().data(),strGateway.length()); STREAM_PACKET tempStreadPacket = LedOkMakeStreamPacket(COMMAND_ONLY_RESET_CARD_IP, 80, (unsigned char *)&stTempIp,"Broadcast!"); int iLenPacket=tempStreadPacket.iLength+sizeof(int)+3*sizeof(unsigned char)+sizeof(char)+20*sizeof(char)+sizeof(char);/////除正文外的协议结构大小; QUdpSocket *tempUdpSocket = new QUdpSocket(this); if(!tempUdpSocket->bind(entry.ip())) break; tempUdpSocket->writeDatagram((char *)&tempStreadPacket,iLenPacket,broadcastAddress, 31296); } } }