#include "CounterWindowRT.h" #include "ui_CounterWindowRT.h" CounterWindowRT::CounterWindowRT(QWidget *parent) : QWidget(parent) , ui(new Ui::CounterWindowRT) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); move(0, 0); resize(SettingConfig::getInstance().WINDOW_WIDTH, SettingConfig::getInstance().WINDOW_HEIGHT); settingForm = new CounterSettingForm(); connect(settingForm, &CounterSettingForm::channelSettingSubmit, this, &CounterWindowRT::onChannelSettingSubmit); QFile file(":/qss/mainClock.css"); if (file.open(QFile::ReadOnly)) { QString qss = QLatin1String(file.readAll()); QString paletteColor = qss.mid(20, 7); qApp->setPalette(QPalette(QColor(paletteColor))); qApp->setStyleSheet(qss); file.close(); } ui->labTitle->setText(QString("钟差测量数据采集软件——%1").arg(SettingConfig::getInstance().MASTER == 1 ? "主" : "备")); // kafka consumer kafkaConsumer = new QKafkaConsumer(this); kafkaConsumer->setBrokers(SettingConfig::getInstance().KAFKA_BROKERS); kafkaConsumer->setTopic(SettingConfig::getInstance().KAFKA_MSG_TOPIC); kafkaConsumer->createConsumer(); kafkaConsumer->start(); connect(kafkaConsumer, &QKafkaConsumer::messageRecieved, this, &CounterWindowRT::onKafkaMessageReceived); // 绘制界面上的表格 initChannelForm(); // 显示时钟 每秒更新 connect(TimerCounterUtil::getInstance().clockCounter, &QTimer::timeout, this, &CounterWindowRT::updateDateAndTime); TimerCounterUtil::getInstance().clockCounter->start(1000); // 重新选择显示多少个计数器 connect(settingForm, &CounterSettingForm::swiftDisplayLoop, this, &CounterWindowRT::updateDeviceWidget); connect(settingForm, &CounterSettingForm::swiftDisplayCount, this, &CounterWindowRT::initChannelForm); httpReq = new HttpRequestController(this); // 1. 获取访问接口需要的token int retCode = this->initHttpToken(); if (retCode != 200) { QMessageBox::information(this, "错误", "获取http请求的token失败,程序即将退出"); QTimer::singleShot(100, qApp, SLOT(quit())); } // 初始化设备和通道 getDeviceList(); // 查询当前报警记录并显示 int alarmCount = httpReq->getSysClockAlarmCount(); if (alarmCount > 0) { QJsonObject alarmRecords = httpReq->getSysClockAlarmList(alarmCount); if (alarmRecords.value("code") == 200) { this->updateDeviceAlarm(alarmRecords.value("data").toObject().value("rows").toArray()); } } // 暂停三秒后打开计数器的串口接收数据 QThread::msleep(1000 * 3); for (int i = 0; i < ConstCache::getInstance().deviceIdLoopA.size(); i++) { CounterDevice * devicePtr = ConstCache::getInstance().deviceMap.value(ConstCache::getInstance().deviceIdLoopA.at(i)); devicePtr->initSerialPort(); } for (int i = 0; i < ConstCache::getInstance().deviceIdLoopB.size(); i++) { CounterDevice * devicePtr = ConstCache::getInstance().deviceMap.value(ConstCache::getInstance().deviceIdLoopB.at(i)); devicePtr->initSerialPort(); } } CounterWindowRT::~CounterWindowRT() { delete ui; } void CounterWindowRT::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Escape: QTimer::singleShot(100, qApp, SLOT(quit())); default: QWidget::keyPressEvent(event); } } void CounterWindowRT::onChannelSettingSubmit(QJsonArray channelSettings) { httpReq->updateChannelInfo(channelSettings); } int CounterWindowRT::initHttpToken() { QJsonObject response = httpReq->getTokenByClientId(SettingConfig::getInstance().CLIENT_ID, SettingConfig::getInstance().APP_KEY); return response.value("code").toInt(); } void CounterWindowRT::getDeviceList() { QJsonObject devListRes = httpReq->initDeviceList(SettingConfig::getInstance().DEV_TYPES, SettingConfig::getInstance().SYSTEM); if (devListRes.value("code").toInt() == 200) { // 将获取到的设备绘制到表格中 QJsonArray devArray = devListRes.value("data").toArray(); for (int i = 0; i < devArray.size(); i++) { // 接口返回的device对象 QJsonObject devItem = devArray.at(i).toObject(); QString devName = devItem.value("simpleName").toString(); // 设备名称 QString deviceId = devItem.value("deviceId").toString(); // 设备ID QString isUse = devItem.value("isUse").toString(); // 标识A路/B路 // 构建Device对象 并赋值id、串口、波特率、设备编号等属性 CounterDevice * device = new CounterDevice(this); device->setDeviceId(deviceId); device->setComName(devItem.value("linkComName").toString()); device->setBaudRate(SettingConfig::getInstance().BAUD_RATE); device->setDevCode(devItem.value("deviceNo").toString()); device->setDeviceName(devName); device->setIsUse(isUse.toInt()); ConstCache::getInstance().deviceMap.insert(deviceId, device); if (isUse == "1") { ConstCache::getInstance().deviceIdLoopA.append(deviceId); } else if (isUse == "0") { ConstCache::getInstance().deviceIdLoopB.append(deviceId); } // 绑定显示函数 connect(device, &CounterDevice::sendDataToDraw, this, &CounterWindowRT::drawCounterDataOnPage); // 查询计数器的通道 并初始化串口 this->getChannelList(deviceId); } updateDeviceWidget(); } } void CounterWindowRT::getChannelList(QString deviceId) { // 查询计数器的通道 QJsonObject response = httpReq->getChannelList(deviceId); if (response.value("code").toInt() == 200) { // 将通道绘制在界面上 QJsonArray channelArray = response.value("data").toArray(); for (int i = 0; i < channelArray.size(); i++) { // 接口返回的channel对象 QJsonObject channelItem = channelArray.at(i).toObject(); QString channelId = channelItem.value("id").toString(); // 通道ID QString channelCode = channelItem.value("channelCode").toString(); // 通道钟号 QString channelNo = QString::number(channelItem.value("channelNo").toInt()); // 通道序号 QString delays = channelItem.value("delays").toString(); // 通道时延值 QString isUse = channelItem.value("isUse").toString(); QString name = channelItem.value("name").toString(); bool active = channelItem.value("isActive").toString().toInt(); // 通道是否启用 // 构建通道对象 并设置属性 CounterChannel * channel = new CounterChannel(this); channel->setDeviceId(deviceId); channel->setChannelId(channelId); channel->setChannelCode(channelCode); channel->setChannelNo(channelNo); channel->setDelays(delays); channel->setActive(active); channel->setIsUse(isUse); channel->setName(name); // 添加到通道的集合中 key=deviceId-channelNo ConstCache::getInstance().channelMap.insert(deviceId + "-" + channelNo, channel); } } } void CounterWindowRT::initDevAndChannelForm(int count) { // 2. 绘制4个计数器的线框,每个计数器显示16个通道 QHBoxLayout * layoutConter = new QHBoxLayout(ui->widgetContent); // 计数器框采用水平布局 layoutConter->setSpacing(10); // 设置计数器设备框之间的间隔为10px layoutConter->setContentsMargins(15, 0, 15, 20); for ( int i = 0; i < count; i++) { // 计数器对应的wideget QWidget * widgetDev = new QWidget(ui->widgetContent); widgetDev->setProperty("form", "dev"); // 添加属性,用于css样式选择 layoutConter->addWidget(widgetDev); // 每个计数器框内为左右布局 QHBoxLayout * layoutChannelPage = new QHBoxLayout(widgetDev); layoutChannelPage->setSpacing(0); // 中间不需要间隔 layoutChannelPage->setMargin(3); // 留出边框的位置 // 左右布局中是垂直布局,用于显示通道 QVBoxLayout * layoutChannelLeft = new QVBoxLayout(); QVBoxLayout * layoutChannelRight = new QVBoxLayout(); layoutChannelLeft->setSpacing(0); layoutChannelRight->setSpacing(0); // 设备标题的Label QLabel * labDevTitle = new QLabel(widgetDev); labDevTitle->setProperty("labType", QString("devTitle%1").arg(count)); // 样式表属性 labDevTitle->setText(QString("计数器-%1").arg(i + 1)); labDevTitle->setAlignment(Qt::AlignCenter); // 文字居中显示 labDevTitle->setStyleSheet("border-top-left-radius: 10px;"); // 左上角的圆角 devTitleList.append(labDevTitle); // 设备参考通道的Label QLabel * labDevRef = new QLabel(widgetDev); labDevRef->setProperty("labType", QString("devTitle%1").arg(count)); // 样式表属性 labDevRef->setText(QString("REF: %1").arg("1000")); labDevRef->setAlignment(Qt::AlignCenter); // 文字居中显示 labDevRef->setStyleSheet("border-top-right-radius: 10px;"); // 右上角的圆角 devRefList.append(labDevRef); if (count == 4) { labDevTitle->setMaximumHeight(80); // 设置固定高度 labDevTitle->setMinimumHeight(80); labDevRef->setMaximumHeight(80); // 设置固定高度 labDevRef->setMinimumHeight(80); } else { labDevTitle->setMaximumHeight(60); // 设置固定高度 labDevTitle->setMinimumHeight(60); labDevRef->setMaximumHeight(60); // 设置固定高度 labDevRef->setMinimumHeight(60); } // 左侧显示设备简称,右侧显示参考通道名 layoutChannelLeft->addWidget(labDevTitle); layoutChannelRight->addWidget(labDevRef); // 每个计数器显示16个通道 for ( int i = 0; i < 16; i++ ) { QLabelDblClick * labChannelName = new QLabelDblClick(widgetDev); // 通道名 QLabelDblClick * labChannelValue = new QLabelDblClick(widgetDev); // 通道测量值 // 默认显示内容 labChannelName->setText(QString("CH%1").arg(i+1, 2, 10, QLatin1Char('0'))); labChannelValue->setText("0.000000000000"); // css不支持的样式用代码实现 labChannelName->setMargin(10); labChannelValue->setMargin(10); labChannelValue->setAlignment(Qt::AlignRight | Qt::AlignVCenter); // 奇偶显示不同的背景色 if (i % 2 == 0) { labChannelName->setProperty("labType", QString("channelNameEven%1").arg(count)); labChannelValue->setProperty("labType", QString("channelValueEven%1").arg(count)); } else { labChannelName->setProperty("labType", QString("channelNameOdd%1").arg(count)); labChannelValue->setProperty("labType", QString("channelValueOdd%1").arg(count)); } layoutChannelLeft->addWidget(labChannelName); layoutChannelRight->addWidget(labChannelValue); // 添加通道名称的双击事件,显示数据和残差图表 connect(labChannelName, &QLabelDblClick::doubleClicked, this, &CounterWindowRT::onChannelNameLabelDblClicked); connect(labChannelValue, &QLabelDblClick::doubleClicked, this, &CounterWindowRT::onChannelNameLabelDblClicked); channelNameList.append(labChannelName); channelValueList.append(labChannelValue); // 左下角和右下角的圆角处理 if (i == 15) { labChannelName->setStyleSheet("border-bottom-left-radius: 10px;"); labChannelValue->setStyleSheet("border-bottom-right-radius: 10px;"); } } layoutChannelPage->addLayout(layoutChannelLeft); layoutChannelPage->addLayout(layoutChannelRight); widgetDev->setLayout(layoutChannelPage); } } void CounterWindowRT::updateChannelDataForm(QJsonArray messageArray) { // 获取设备id属性 QString deviceId = messageArray.at(0).toObject().value("deviceId").toString(); // 参考通道号 int refChNo = messageArray.at(0).toObject().value("data").toObject().value("channelRefNo").toInt(); // 根据设备id 从map中取出列索引的值 int devIdx = ConstCache::getInstance().deviceMap.value(deviceId)->getFormColIndex(); if (devIdx < devRefList.size()) { // 参考通道的显示 QString refText = devRefList.at(devIdx)->text(); channelNameList.at(devIdx * 16 + refChNo - 1)->setText(QString("CH%1:%2").arg(refChNo, 2, 10, QLatin1Char('0')).arg(refText.right(refText.length() - 4))); } QMap<QString, QJsonObject> channelDataJsonMap; for (int i = 0; i < messageArray.size(); i++) { QJsonObject channelDataItem = messageArray.at(i).toObject(); QString channelNo = QString::number(channelDataItem.value("channelNo").toInt()); // 通道序号 channelDataJsonMap.insert(channelNo, channelDataItem); } CounterChannel * refChanPtr = ConstCache::getInstance().channelMap.value(QString("%1-%2").arg(deviceId).arg(refChNo)); double refDelay = 0.0; if (refChanPtr != nullptr && refChanPtr->getDelays().isEmpty() == false) { refDelay = refChanPtr->getDelays().toDouble(); } // 逐个通道显示 for (int i = 0; i < 16; i++) { QString channelNo = QString::number(i + 1); QString channelNoStr = QString("%1").arg(i + 1, 2, 10, QLatin1Char('0')); if (i + 1 == refChNo) { continue; } if (channelDataJsonMap.contains(channelNo) == true) { QJsonObject channelDataItem = channelDataJsonMap.value(channelNo); CounterChannel * channel = ConstCache::getInstance().channelMap.value(deviceId + "-" + channelNo); // 从map中找到对应的通道 // 通道Label的序号 int chanelIdx = devIdx * 16 + channelDataItem.value("channelNo").toInt() - 1; if (channel != nullptr && channel->isActive() == true) { // 通道时延值 并计算 减去时延值的测量值 double delay = channel->getDelays().isEmpty() == false ? channel->getDelays().toDouble() : 0.0; double valueMinusDelay = channelDataItem.value("data").toObject().value("dataValue").toString().toDouble() - delay * 1E-9 + refDelay * 1E-9; // 设置通道名和测量值的QLabel channelNameList.at(chanelIdx)->setText(QString("CH%1:%2").arg(channelNoStr).arg(channel->getChannelCode())); channelValueList.at(chanelIdx)->setText(QString::number(valueMinusDelay, 'f', 12)); channelNameList.at(chanelIdx)->setProperty("channelId", channel->getChannelId()); channelNameList.at(chanelIdx)->setProperty("deviceId", deviceId); channelNameList.at(chanelIdx)->setProperty("channelNo", channelNo); channelValueList.at(chanelIdx)->setProperty("channelId", channel->getChannelId()); channelValueList.at(chanelIdx)->setProperty("deviceId", deviceId); channelValueList.at(chanelIdx)->setProperty("channelNo", channelNo); } else { channelNameList.at(chanelIdx)->setText(QString("CH%1:%2").arg(channelNoStr).arg("-")); channelValueList.at(chanelIdx)->setText(""); } } else { // 没有测量值的通道清空 channelNameList.at(devIdx * 16 + i)->setText(QString("CH%1:%2").arg(channelNoStr).arg("-")); channelValueList.at(devIdx * 16 + i)->setText(""); channelNameList.at(devIdx * 16 + i)->setProperty("labType", "channelNameAlarm"); channelValueList.at(devIdx * 16 + i)->setProperty("labType", "channelValueAlarm"); } } } void CounterWindowRT::updateDeviceAlarm(QJsonArray alarmList) { QVector<QString> alarmDev; QVector<QString> alarmChannel; for (int i = 0; i < alarmList.size(); i++) { QJsonObject alarmData = alarmList.at(i).toObject(); QString deviceId = alarmData.value("deviceId").toString(); QString channelId = alarmData.value("channelId").toString(); QString level = alarmData.value("level").toString(); QString status = alarmData.value("status").toString(); if (alarmDev.contains(deviceId) == false) { alarmDev.append(deviceId); } // CounterChannel * } for (int i = 0; i < alarmDev.size(); i++) { CounterDevice * devicePtr = ConstCache::getInstance().deviceMap.value(alarmDev.at(i)); if (devicePtr != nullptr) { if (settingForm->getDisplayGroupFlag() == 1) { if (ConstCache::getInstance().deviceIdLoopA.contains(alarmDev.at(i))) { ((QWidget *)ui->widgetContent->children().at(devicePtr->getFormColIndex() + 1))->setProperty("form", "devAlarm"); this->setDevAndChannelAlarm(devicePtr->getFormColIndex(), 0, 0); } } else if (settingForm->getDisplayGroupFlag() == 0) { if (ConstCache::getInstance().deviceIdLoopB.contains(alarmDev.at(i))) { qDebug() << "B: " << devicePtr->getFormColIndex() << ui->widgetContent->children().size(); } } } } } CounterChannel * CounterWindowRT::getChannelByDevAndId(QString deviceId, QString channelId) { if (deviceId.isEmpty() == true || channelId.isEmpty() == true) return nullptr; for (int i = 1; i <= 16; i++) { QString key = QString("%1-%2").arg(deviceId).arg(i); CounterChannel * channelPtr = ConstCache::getInstance().channelMap.value(key); if (channelPtr != nullptr) { if (channelPtr->getChannelId() == channelId) { return channelPtr; } } } return nullptr; } void CounterWindowRT::setDevAndChannelAlarm(int devIndex, int channelIndex, bool alarm) { // TODO ((QWidget *) ui->widgetContent->children().at(devIndex + 1))->setStyleSheet("border: 3px solid #FF0000"); for (int i = 1; i < ui->widgetContent->children().at(devIndex + 1)->children().size(); i++) { ((QWidget *) ui->widgetContent->children().at(devIndex + 1)->children().at(i))->setStyleSheet("border: 0px;"); } devTitleList.at(devIndex)->setStyleSheet("border-top-left-radius: 10px; border: 3px solid #1E5A7C;"); devRefList.at(devIndex)->setStyleSheet("border-top-right-radius: 10px; border: 3px solid #1E5A7C;"); channelNameList.at(devIndex * 16 + 15)->setStyleSheet("border-bottom-left-radius: 10px; border: 3px solid #123553;"); channelValueList.at(devIndex * 16 + 15)->setStyleSheet("border-bottom-right-radius: 10px; border: 3px solid #123553;"); } void CounterWindowRT::updateDateAndTime() { QString date = QDate::currentDate().toString("yyyy-MM-dd"); QString time = QTime::currentTime().toString("HH:mm:ss"); ui->labTime->setText(date + " " + time); } void CounterWindowRT::on_btnMenuSetting_clicked() { settingForm->setWindowModality(Qt::ApplicationModal); settingForm->setWindowTitle("系统设置"); settingForm->initCounterSelect(); settingForm->show(); } void CounterWindowRT::on_btnMenuMin_clicked() { setWindowState(Qt::WindowMinimized | windowState()); } void CounterWindowRT::initChannelForm() { // 1. 首先清除界面上的所有内容 qDeleteAll(ui->widgetContent->children()); // 将lab列表的数量置0 devTitleList.resize(0); devRefList.resize(0); channelNameList.resize(0); channelValueList.resize(0); initDevAndChannelForm(SettingConfig::getInstance().DISPLAY_COUNT); } void CounterWindowRT::updateDeviceWidget() { QList<QString> devIds = SettingConfig::getInstance().MASTER == 1 ? ConstCache::getInstance().deviceIdLoopA : ConstCache::getInstance().deviceIdLoopB; for (int i = 0; i < SettingConfig::getInstance().DISPLAY_COUNT; i++) { if (i < devIds.size()) { CounterDevice * dev = ConstCache::getInstance().deviceMap.value(devIds.at(i)); if (dev != nullptr) { devTitleList.at(i)->setText(dev->getDeviceName()); // 设备名称 dev->setFormColIndex(i); } } else { devTitleList.at(i)->setText(""); devRefList.at(i)->setText(""); for (int j = 0; j < 16; j++) { channelNameList.at(i * 16 + j)->setText(""); channelValueList.at(i * 16 + j)->setText(""); } } } } void CounterWindowRT::onChannelNameLabelDblClicked() { QLabelDblClick * channelLab = (QLabelDblClick *) sender(); QString deviceId = channelLab->property("deviceId").toString(); QString channelNo = channelLab->property("channelNo").toString(); CounterChannel * channel = ConstCache::getInstance().channelMap.value(deviceId + "-" + channelNo); if (channel != nullptr) { CounterDevice * device = ConstCache::getInstance().deviceMap.value(deviceId); QString deviceName = device != nullptr ? device->getDeviceName() : ""; ChannelChartForm * chartFrame = new ChannelChartForm(); chartFrame->setWindowModality(Qt::ApplicationModal); chartFrame->initDataChart(channel->getHisData()); chartFrame->setTitleText((QString("%1 通道%2 历史数据").arg(deviceName).arg(channelNo))); chartFrame->show(); } } /** * @brief CounterWindowRT::drawCounterDataOnPage * @param messageArray * 根据发送到Kafka中的数据串来绘制界面 * */ void CounterWindowRT::drawCounterDataOnPage(QJsonArray messageArray) { if (messageArray.isEmpty() == false) { // 获取设备id属性 QString deviceId = messageArray.at(0).toObject().value("deviceId").toString(); // 如果不是当前显示的计数器 则直接返回 CounterDevice * devicePtr = ConstCache::getInstance().deviceMap.value(deviceId); if (devicePtr == nullptr || SettingConfig::getInstance().MASTER != devicePtr->getIsUse()) { return; } // 根据设备id 从map中取出列索引的值 int devIdx = devicePtr->getFormColIndex(); if (devIdx > SettingConfig::getInstance().DISPLAY_COUNT) { return; } // 参考通道 int refChNo = messageArray.at(0).toObject().value("data").toObject().value("channelRefNo").toInt(); CounterChannel * refChann = ConstCache::getInstance().channelMap.value(QString("%1-%2").arg(deviceId).arg(refChNo)); if (refChann != nullptr) { if (devIdx < devRefList.size()) { devRefList.at(devIdx)->setText(QString("REF:%1").arg(refChann->getChannelCode())); } } updateChannelDataForm(messageArray); } } void CounterWindowRT::onKafkaMessageReceived(QJsonObject message) { qDebug() << message; std::cout << QString(QJsonDocument(message).toJson(QJsonDocument::Compact)).toStdString() << std::endl; // 找不到deviceId deviceType operation三个必填项 直接返回 if (message.contains("deviceId") == false || message.contains("operation") == false || message.contains("deviceType") == false) { return; } // deviceType不是计数器 直接返回 if (message.value("deviceType").toString() != "01") { return; } QString deviceId = message.value("deviceId").toString(); if (message.contains("chanelId") == true) { this->getChannelList(deviceId); } else { ConstCache::getInstance().channelMap.clear(); ConstCache::getInstance().deviceMap.clear(); this->getDeviceList(); } }