Newer
Older
ZXSSCJ / CounterRealTime / CounterWindowRT.cpp
#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);

        int n[3] = {4, 6, 8};
        for (int i = 0; i < SettingConfig::getInstance().HARD_CODE_QSS.size(); i++)
        {
            for (int j = 0; j < 3; j++) {
                QString name = QString("%1%2").arg(SettingConfig::getInstance().HARD_CODE_QSS.at(i)).arg(n[j]);
                int nameIdx = qss.indexOf(name);
                int start = qss.indexOf("{", nameIdx) + 1;
                int end = qss.indexOf("}", nameIdx);
                ConstCache::getInstance().qssConstMap.insert(name, qss.mid(start, end - start).replace("\n", "").replace(" ", ""));
            }
        }
        int nameIdx = qss.indexOf("channelAlarm");
        int start = qss.indexOf("{", nameIdx) + 1;
        int end = qss.indexOf("}", nameIdx);
        ConstCache::getInstance().qssConstMap.insert("channelAlarm", qss.mid(start, end - start).replace("\n", "").replace(" ", ""));

        nameIdx = qss.indexOf("channelOffline");
        start = qss.indexOf("{", nameIdx) + 1;
        end = qss.indexOf("}", nameIdx);
        ConstCache::getInstance().qssConstMap.insert("channelOffline", qss.mid(start, end - start).replace("\n", "").replace(" ", ""));

        nameIdx = qss.indexOf("devTitleAlarm");
        start = qss.indexOf("{", nameIdx) + 1;
        end = qss.indexOf("}", nameIdx);
        ConstCache::getInstance().qssConstMap.insert("devTitleAlarm", qss.mid(start, end - start).replace("\n", "").replace(" ", ""));

        nameIdx = qss.indexOf("devRefAlarm");
        start = qss.indexOf("{", nameIdx) + 1;
        end = qss.indexOf("}", nameIdx);
        ConstCache::getInstance().qssConstMap.insert("devRefAlarm", qss.mid(start, end - start).replace("\n", "").replace(" ", ""));

        nameIdx = qss.indexOf("devTitleOffline");
        start = qss.indexOf("{", nameIdx) + 1;
        end = qss.indexOf("}", nameIdx);
        ConstCache::getInstance().qssConstMap.insert("devTitleOffline", qss.mid(start, end - start).replace("\n", "").replace(" ", ""));

        nameIdx = qss.indexOf("devRefOffline");
        start = qss.indexOf("{", nameIdx) + 1;
        end = qss.indexOf("}", nameIdx);
        ConstCache::getInstance().qssConstMap.insert("devRefOffline", qss.mid(start, end - start).replace("\n", "").replace(" ", ""));

        file.close();
    }

    ui->labTitle->setText(QString("钟差测量数据采集软件——%1").arg(SettingConfig::getInstance().MASTER == 1 ? "主" : "备"));

    if (SettingConfig::getInstance().NEED_KAFKA == 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);

        // kafka consumer
        alarmMsgConsumer = new QKafkaConsumer(this);
        alarmMsgConsumer->setBrokers(SettingConfig::getInstance().KAFKA_BROKERS);
        alarmMsgConsumer->setTopic(SettingConfig::getInstance().KAFKA_ALARM_TOPIC);
        alarmMsgConsumer->createConsumer();
        alarmMsgConsumer->start();
        connect(alarmMsgConsumer, &QKafkaConsumer::messageRecieved, this, &CounterWindowRT::onAlarmMessageReceived);
    }

    // 绘制界面上的表格
    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());
        }
    }

    // 启动服务监听
    HttpServer::instance().run(QHostAddress::Any, SettingConfig::getInstance().SERVER_PORT);

    // 8. 备路应用定时向主路应用请求以判定主路应用的状态
    if (SettingConfig::getInstance().MASTER == 0) {
        connect(TimerCounterUtil::getInstance().heartCounter, &QTimer::timeout, this, &CounterWindowRT::onCounterMaserHeartHandle);
        TimerCounterUtil::getInstance().heartCounter->start(1000);
    }

    // 打开计数器的串口接收数据
    QThread::msleep(1000);
    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);
        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); // 文字居中显示
        devTitleList.append(labDevTitle);

        // 设备参考通道的Label
        QLabel * labDevRef = new QLabel(widgetDev);
        labDevRef->setProperty("labType", QString("devRef%1").arg(count)); // 样式表属性
        labDevRef->setText(QString("REF: %1").arg("1000"));
        labDevRef->setAlignment(Qt::AlignCenter); // 文字居中显示
        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)));

        if (alarmDev.contains(deviceId) == true)
        {
            devTitleList.at(devIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value("devTitleAlarm"));
            devRefList.at(devIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value("devRefAlarm"));
        } else if (offlineDev.contains(deviceId) == true)
        {
            devTitleList.at(devIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value("devTitleOffline"));
            devRefList.at(devIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value("devRefOffline"));
        } else {
            devTitleList.at(devIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value(devTitleList.at(devIdx)->property("labType").toString()));
            devRefList.at(devIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value(devRefList.at(devIdx)->property("labType").toString()));
        }
    }

    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 channelIdx = devIdx * 16 + channelDataItem.value("channelNo").toInt() - 1;

            if (alarmChannel.contains(channel->getChannelId()) == true)
            {
                channelNameList.at(channelIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value("channelAlarm"));
                channelValueList.at(channelIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value("channelAlarm"));
            } else if (offlineChannel.contains(channel->getChannelId()) == true)
            {
                channelNameList.at(channelIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value("channelOffline"));
                channelValueList.at(channelIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value("channelOffline"));
            } else {
                channelNameList.at(channelIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value(channelNameList.at(channelIdx)->property("labType").toString()));
                channelValueList.at(channelIdx)->setStyleSheet(ConstCache::getInstance().qssConstMap.value(channelValueList.at(channelIdx)->property("labType").toString()));
            }

            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(channelIdx)->setText(QString("CH%1:%2").arg(channelNoStr).arg(channel->getChannelCode()));
                channelValueList.at(channelIdx)->setText(QString::number(valueMinusDelay, 'f', 12));

                channelNameList.at(channelIdx)->setProperty("channelId", channel->getChannelId());
                channelNameList.at(channelIdx)->setProperty("deviceId", deviceId);
                channelNameList.at(channelIdx)->setProperty("channelNo", channelNo);

                channelValueList.at(channelIdx)->setProperty("channelId", channel->getChannelId());
                channelValueList.at(channelIdx)->setProperty("deviceId", deviceId);
                channelValueList.at(channelIdx)->setProperty("channelNo", channelNo);
            } else {
                channelNameList.at(channelIdx)->setText(QString("CH%1:%2").arg(channelNoStr).arg("-"));
                channelValueList.at(channelIdx)->setText("");
            }
        } else {
            // 没有测量值的通道清空
            channelNameList.at(devIdx * 16 + i)->setText(QString("CH%1:%2").arg(channelNoStr).arg("-"));
            channelValueList.at(devIdx * 16 + i)->setText("");
        }
    }
}

void CounterWindowRT::updateDeviceAlarm(QJsonArray alarmList)
{
    qDebug() << alarmList;
    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 alarmCode = alarmData.value("alarmCode").toString();
        QString status = alarmData.value("status").toString();

        qDebug() << alarmCode << deviceId << channelId;

        // 如果报警状态不是正在报警 status==0 或者报警设备不是计数器 则不处理
        if (status != "0" || ConstCache::getInstance().deviceMap.contains(deviceId) == false)
        {
            continue;
        }

        // 是设备级的报警
        if (SettingConfig::getInstance().DEVICE_ALARM_CODES.contains(alarmCode) == true && alarmDev.contains(deviceId) == false) {
            if (alarmCode == "DEVICE_OFFLINE") {
                offlineDev.append(deviceId);
            } else if (alarmCode == "DEVICE_ALARM") {
                alarmDev.append(deviceId);
            }
        }

        if (channelId.isEmpty() == false && SettingConfig::getInstance().CHANNEL_ALARM_CODES.contains(alarmCode) == true && alarmChannel.contains(channelId) == false) {
            if (alarmCode == "COUNTER_NO_DATA") {
                offlineChannel.append(channelId);
            } else if (alarmCode == "FREQUENCY_HOPPING" || alarmCode == "PHASE_HOPPING" || alarmCode == "BAD_DATA" || alarmCode == "DATA_EXCEPTION") {
                alarmChannel.append(channelId);
            }
        }
    }
}

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();
    }
}

void CounterWindowRT::onAlarmMessageReceived(QJsonObject alarmMsg)
{
    qDebug() << alarmMsg;
    std::cout << QString(QJsonDocument(alarmMsg).toJson(QJsonDocument::Compact)).toStdString() << std::endl;

    QString deviceId = alarmMsg.value("deviceId").toString();
    QString channelId = alarmMsg.value("channelId").toString();
    QString alarmCode = alarmMsg.value("alarmCode").toString();
    QString status = alarmMsg.value("status").toString();

    if (ConstCache::getInstance().deviceMap.contains(deviceId) == false) {
        return;
    }

    // 是设备级的报警
    if (SettingConfig::getInstance().DEVICE_ALARM_CODES.contains(alarmCode) == true) {
        if (status == "0")
        {
            // 之前是正常的状态 新增报警状态
            if (alarmCode == "DEVICE_OFFLINE" && offlineDev.contains(deviceId) == false) {
                offlineDev.append(deviceId);
            } else if (alarmCode == "DEVICE_ALARM" && alarmDev.contains(deviceId) == false) {
                alarmDev.append(deviceId);
            }
        } else if (status == "2" || status == "1")
        {
            // 消警的逻辑
            if (alarmCode == "DEVICE_OFFLINE" && offlineDev.contains(deviceId) == true) {
                offlineDev.removeOne(deviceId);
            } else if (alarmCode == "DEVICE_ALARM" && alarmDev.contains(deviceId) == true) {
                alarmDev.removeOne(deviceId);
            }
        }
    }

    // 是通道级的报警
    if (channelId.isEmpty() == false && SettingConfig::getInstance().CHANNEL_ALARM_CODES.contains(alarmCode) == true) {
        if (status == "0")
        {
            // 之前是正常的状态 新增报警状态
            if (alarmCode == "COUNTER_NO_DATA" && alarmChannel.contains(channelId) == false) {
                offlineChannel.append(channelId);
            } else if (alarmCode == "FREQUENCY_HOPPING" || alarmCode == "PHASE_HOPPING" || alarmCode == "BAD_DATA" || alarmCode == "DATA_EXCEPTION" &&
                       alarmChannel.contains(channelId) == false) {
                alarmChannel.append(channelId);
            }
        } else if (status == "2" || status == "1")
        {
            // 消警的逻辑
            if (alarmCode == "COUNTER_NO_DATA" && offlineChannel.contains(channelId) == true) {
                offlineChannel.removeOne(channelId);
            } else if (alarmCode == "FREQUENCY_HOPPING" || alarmCode == "PHASE_HOPPING" || alarmCode == "BAD_DATA" || alarmCode == "DATA_EXCEPTION" &&
                       alarmChannel.contains(channelId) == true) {
                alarmChannel.removeOne(channelId);
            }
        }
    }
}

void CounterWindowRT::onCounterMaserHeartHandle()
{
    QJsonObject heartRet = httpReq->counterMasterHeartBeat();
    if (heartRet.value("code") == 200) {
        QMutex mutex;
        mutex.lock();
        ConstCache::getInstance().latestHeartTs = QDateTime::currentDateTime().currentSecsSinceEpoch();
        mutex.unlock();
    }
}