From fd6fe87f06ed0ff3b304323f4a8162293544cd5b Mon Sep 17 00:00:00 2001 From: duanshengchao <519970194@qq.com> Date: Sun, 4 Jan 2026 09:51:02 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E5=AE=8C=E6=88=90=E6=9C=AC=E5=9C=B0?= =?UTF-8?q?=E7=BC=93=E5=AD=98=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/alarmEventDataService.h | 2 +- include/measurementDataManager.h | 16 +++- measurementDataService_config.ini | 3 +- source/alarmEventDataService.cpp | 7 +- source/measurementDataManager.cpp | 120 ++++++++++++++++++++++++++++-- ui/dashboardFrame.ui | 10 +-- 6 files changed, 137 insertions(+), 21 deletions(-) diff --git a/include/alarmEventDataService.h b/include/alarmEventDataService.h index ab1672d..e520979 100644 --- a/include/alarmEventDataService.h +++ b/include/alarmEventDataService.h @@ -61,7 +61,7 @@ private: MessageHandleResult processMessage(const QAmqpMessage& message); bool validateEvent(const EventData& event); //历史数据处理 - QUrl bulidHistoricalQueryUrl(const QDateTime& startTime, const QDateTime& endTime, int confirmStatus); + QUrl buildHistoricalQueryUrl(const QDateTime& startTime, const QDateTime& endTime, int confirmStatus); void processHistoricalResponse(const QByteArray& data); //QNetworkRequest createHistoricalRequest(const QUrl& url); //事件确认 diff --git a/include/measurementDataManager.h b/include/measurementDataManager.h index 9af4b92..d41af80 100644 --- a/include/measurementDataManager.h +++ b/include/measurementDataManager.h @@ -2,10 +2,14 @@ #define MEASUREMENTDATAMANAGER_H #include +#include +#include + class QSettings; class QNetworkAccessManager; class QNetworkReply; class WebSocketClient; +class MeasurementData; class MeasurementDataManager : public QObject { @@ -20,9 +24,11 @@ public: void addSubscriptionData(const QStringList& measurements); void removeSubscriptionData(const QStringList& measurements); void getSubscriptionRealtimeData(); + void queryHistoricalEvents(const QString& dataID, const QDateTime& startTime, const QDateTime& endTime, const QString& step, const QString& type = "phasor"); private slots: - void onReciveRealtimeData(const QString& dataMsg); + void onReceiveRealtimeData(const QString& dataMsg); + void onHistoricalRequestFinished(const QString& dataID, QNetworkReply* reply); private: struct RealtimeConfig @@ -44,8 +50,7 @@ private: struct HistoricalConfig { - QString host; - int port; + QUrl baseUrl; int timeout; //请求超时(毫秒) int maxRetries; //最大重试次数 int retryInterval; //重试间隔 @@ -69,6 +74,8 @@ private: void initialize(); void buildSubscriptionRequest(const QString& action, const QStringList& measurements); void processSubscriptionResponse(const QString& action, QNetworkReply* reply); + QUrl buildHistoricalQueryUrl(const QString& dataID,const QDateTime& startTime, const QDateTime& endTime, const QString& step, const QString& type); + void processHistoricalResponse(const QString& dataID, const QByteArray& data); //配置相关 ServiceConfig m_serviceConfig; @@ -80,6 +87,9 @@ private: QString m_clientID; QNetworkAccessManager* m_networkManager; WebSocketClient* m_webSocketClient; + + //数据缓存 + QHash> m_dataCache; }; #endif diff --git a/measurementDataService_config.ini b/measurementDataService_config.ini index aa80e6b..028bd65 100644 --- a/measurementDataService_config.ini +++ b/measurementDataService_config.ini @@ -5,5 +5,4 @@ httpPath=monitors/data/subscriptions websocketPath=monitors/data/realtime/stream [HistoricalData] -host=192.168.46.100 -port=10080 \ No newline at end of file +baseUrl=http://192.168.46.30:8888/api/points \ No newline at end of file diff --git a/source/alarmEventDataService.cpp b/source/alarmEventDataService.cpp index 15288fb..ed8fb64 100644 --- a/source/alarmEventDataService.cpp +++ b/source/alarmEventDataService.cpp @@ -68,7 +68,7 @@ void AlarmEventDataService::initialize() m_config.rabbitMQConfig.heartbeat = m_settings->value("RabbitMQConfig/heartbeat").toInt(); m_config.rabbitMQConfig.autoAck = m_settings->value("RabbitMQConfig/autoAck").toBool(); //HistoricalDataConfig - m_config.historicalConfig.baseUrl = m_settings->value("HistoricalDataConfig/baseUrl").toString(); + m_config.historicalConfig.baseUrl = m_settings->value("HistoricalDataConfig/baseUrl").toUrl(); m_config.historicalConfig.timeout = m_settings->value("HistoricalDataConfig/timeout").toInt(); m_config.historicalConfig.maxRetries = m_settings->value("HistoricalDataConfig/maxRetries").toInt(); m_config.historicalConfig.retryInterval = m_settings->value("HistoricalDataConfig/retryInterval").toInt(); @@ -99,7 +99,7 @@ void AlarmEventDataService::stop() void AlarmEventDataService::queryHistoricalEvents(const QDateTime& startTime, const QDateTime& endTime, int confirmStatus) { - QUrl url = bulidHistoricalQueryUrl(startTime, endTime, confirmStatus); + QUrl url = buildHistoricalQueryUrl(startTime, endTime, confirmStatus); //QUrl url = m_config.historicalConfig.baseUrl; if(!url.isValid()) return; @@ -251,7 +251,7 @@ bool AlarmEventDataService::validateEvent(const EventData& event) return true; } -QUrl AlarmEventDataService::bulidHistoricalQueryUrl(const QDateTime& startTime, const QDateTime& endTime, int confirmStatus) +QUrl AlarmEventDataService::buildHistoricalQueryUrl(const QDateTime& startTime, const QDateTime& endTime, int confirmStatus) { QUrl url = m_config.historicalConfig.baseUrl; QUrlQuery query; @@ -276,6 +276,7 @@ void AlarmEventDataService::processHistoricalResponse(const QByteArray& data) .arg(parseError.errorString()) .arg(parseError.offset); emit historicalQueryError(errorMsg); + return; } if(!doc.isObject()) diff --git a/source/measurementDataManager.cpp b/source/measurementDataManager.cpp index 23e24cc..6f6a293 100644 --- a/source/measurementDataManager.cpp +++ b/source/measurementDataManager.cpp @@ -27,7 +27,7 @@ MeasurementDataManager::MeasurementDataManager() , m_webSocketClient(new WebSocketClient(this)) { initialize(); - connect(m_webSocketClient, &WebSocketClient::dataReceived, this, &MeasurementDataManager::onReciveRealtimeData); + connect(m_webSocketClient, &WebSocketClient::dataReceived, this, &MeasurementDataManager::onReceiveRealtimeData); } MeasurementDataManager::~MeasurementDataManager() @@ -49,8 +49,7 @@ void MeasurementDataManager::initialize() m_serviceConfig.realtimeCfg.httpPath = m_settings->value("RealtimeData/httpPath").toString(); m_serviceConfig.realtimeCfg.websocketPath = m_settings->value("RealtimeData/websocketPath").toString(); - m_serviceConfig.historicalCfg.host = m_settings->value("HistoricalData/host").toString(); - m_serviceConfig.historicalCfg.port = m_settings->value("HistoricalData/port").toInt(); + m_serviceConfig.historicalCfg.baseUrl = m_settings->value("HistoricalData/baseUrl").toUrl(); } else { @@ -209,6 +208,71 @@ void MeasurementDataManager::processSubscriptionResponse(const QString& action, reply->deleteLater(); } +QUrl MeasurementDataManager::buildHistoricalQueryUrl(const QString& dataID, const QDateTime& startTime, const QDateTime& endTime, const QString& step, const QString& type) +{ + QUrl url = m_serviceConfig.historicalCfg.baseUrl; + QUrlQuery query; + query.addQueryItem("mtag", dataID); + query.addQueryItem("type", type); + query.addQueryItem("step", step); + query.addQueryItem("begin", QString::number(startTime.toMSecsSinceEpoch())); + query.addQueryItem("end", QString::number(endTime.toMSecsSinceEpoch())); + url.setQuery(query); + return url; +} + +void MeasurementDataManager::processHistoricalResponse(const QString& dataID, const QByteArray& data) +{ + QJsonParseError parseError; + QJsonDocument doc = QJsonDocument::fromJson(data, &parseError); + + if(parseError.error != QJsonParseError::NoError) + { + QString errorMsg = QString("Historical Events JSON parse error: %1 at offset %2") + .arg(parseError.errorString()) + .arg(parseError.offset); + LOG_ERROR("Http-MeasurementData-Historical", errorMsg); + return; + } + + if(!doc.isObject()) + { + QString errorMsg = "Historical Events JSON document is not an object"; + LOG_ERROR("Http-MeasurementData-Historical", errorMsg); + return ; + } + + QJsonObject obj = doc.object(); + int code = obj.value("code").toInt(); + if(code != 0) + { + QString msg = obj.value("msg").toString(); + LOG_ERROR("Http-MeasurementData-Historical", msg); + return ; + } + + QJsonValue dataValue = obj.value("data"); + if(dataValue.isObject()) + { + QJsonObject dataObj = dataValue.toObject(); + QJsonValue values = dataObj.value(dataID); + if(values.isArray()) + { + QJsonArray valueArray = values.toArray(); + int size = valueArray.size(); + for(int i = 0; i < size; ++i) + { + if(!valueArray.at(i).isObject()) + continue; + + QJsonObject valueObj = valueArray.at(i).toObject(); + qint64 timeStamp = valueObj.value("time").toString().toLongLong(); + double value = dataObj.value("value").toDouble(); + } + } + } +} + void MeasurementDataManager::getSubscriptionRealtimeData() { if(m_clientID.isEmpty()) @@ -221,12 +285,28 @@ void MeasurementDataManager::getSubscriptionRealtimeData() QUrl url(strUrl); if(!m_webSocketClient->connectToServer(url)) { - QString errorMsg = QString("Connect to WebSocketServer failed."); + QString errorMsg = QString("Connect to WebSocketServer failed"); LOG_ERROR("WebSocket", errorMsg); } } -void MeasurementDataManager::onReciveRealtimeData(const QString& dataMsg) +void MeasurementDataManager::queryHistoricalEvents(const QString& dataID, const QDateTime& startTime, const QDateTime& endTime, const QString& step, const QString& type) +{ + QUrl url = buildHistoricalQueryUrl(dataID, startTime, endTime, step, type); + if(!url.isValid()) + return; + + //创建网络请求 + QNetworkRequest request(url); + request.setTransferTimeout(m_serviceConfig.historicalCfg.timeout); + //发送请求 + QNetworkReply* reply = m_networkManager->get(request); + connect(reply, &QNetworkReply::finished, this, [this, dataID, reply](){ + onHistoricalRequestFinished(dataID, reply); + }); +} + +void MeasurementDataManager::onReceiveRealtimeData(const QString& dataMsg) { QJsonParseError parseError; QJsonDocument doc = QJsonDocument::fromJson(dataMsg.toUtf8(), &parseError); @@ -251,19 +331,28 @@ void MeasurementDataManager::onReciveRealtimeData(const QString& dataMsg) QJsonObject targetObj = targetValue.toObject(); QString dataID = targetObj.value("id").toString(); + QSharedPointer measurementData; + if(m_dataCache.contains(dataID)) + measurementData = m_dataCache.value(dataID); + QJsonValue datasValue = targetObj.value("datas"); if(datasValue.isArray()) { QJsonArray datasArray = datasValue.toArray(); + QVector dataPoints; + dataPoints.reserve(datasArray.size()); for(const QJsonValue& dataValue : std::as_const(datasArray)) { if(!dataValue.isObject()) continue; QJsonObject dataObj = dataValue.toObject(); - QString timestamp = dataObj.value("time").toString(); - QString value = dataObj.value("value").toString(); + qint64 timestamp = dataObj.value("time").toString().toLongLong(); + double value = dataObj.value("value").toDouble(); + dataPoints.append(MeasurementDataPoint(timestamp, value)); } + //插入数据 + measurementData->insertData(dataPoints); } } } @@ -286,3 +375,20 @@ void MeasurementDataManager::onReciveRealtimeData(const QString& dataMsg) LOG_ERROR("WebSockt-MeasurementData", errorMsg); } } + +void MeasurementDataManager::onHistoricalRequestFinished(const QString& dataID, QNetworkReply* reply) +{ + if(reply->error() == QNetworkReply::NoError) + { + QByteArray data = reply->readAll(); + processHistoricalResponse(dataID, data); + LOG_INFO("Http-MeasurementData-Historical", QString(data)); + } + else + { + QString errorMsg = QString("Request HistoricalData error: %1").arg(/*reply->request().url().toDisplayString(),*/ reply->errorString()); + LOG_ERROR("Http-MeasurementData-Historical", errorMsg); + } + + reply->deleteLater(); +} diff --git a/ui/dashboardFrame.ui b/ui/dashboardFrame.ui index bf1741d..c2d0ef0 100644 --- a/ui/dashboardFrame.ui +++ b/ui/dashboardFrame.ui @@ -6,8 +6,8 @@ 0 0 - 1256 - 773 + 1424 + 890 @@ -148,7 +148,7 @@ icon: url(:/images/icon_event.png); } QPushButton:hover { -background-color: rgb(55,131,204); +background-color: rgba(55,131,204,200); } QPushButton:pressed { @@ -184,10 +184,10 @@ background-color: rgb(67,160,249); font: 700 12pt "微软雅黑"; color:rgb(250,250,250); text-align:right; -padding-right:35px; -background-color: rgb(64, 182, 113); icon-size:20px; icon: url(:/images/icon_add.png); +padding-right:35px; +background-color: rgb(64, 182, 113); } QPushButton:hover {