feat:完成本地缓存结构

This commit is contained in:
duanshengchao 2026-01-04 09:51:02 +08:00
parent 78437aee5e
commit fd6fe87f06
6 changed files with 137 additions and 21 deletions

View File

@ -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);
//事件确认

View File

@ -2,10 +2,14 @@
#define MEASUREMENTDATAMANAGER_H
#include <QObject>
#include <QHash>
#include <QUrl>
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<QString, QSharedPointer<MeasurementData>> m_dataCache;
};
#endif

View File

@ -5,5 +5,4 @@ httpPath=monitors/data/subscriptions
websocketPath=monitors/data/realtime/stream
[HistoricalData]
host=192.168.46.100
port=10080
baseUrl=http://192.168.46.30:8888/api/points

View File

@ -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())

View File

@ -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> measurementData;
if(m_dataCache.contains(dataID))
measurementData = m_dataCache.value(dataID);
QJsonValue datasValue = targetObj.value("datas");
if(datasValue.isArray())
{
QJsonArray datasArray = datasValue.toArray();
QVector<MeasurementDataPoint> 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();
}

View File

@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>1256</width>
<height>773</height>
<width>1424</width>
<height>890</height>
</rect>
</property>
<property name="windowTitle">
@ -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 &quot;微软雅黑&quot;;
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
{