feat:完成本地缓存结构
This commit is contained in:
parent
78437aee5e
commit
fd6fe87f06
|
|
@ -61,7 +61,7 @@ private:
|
||||||
MessageHandleResult processMessage(const QAmqpMessage& message);
|
MessageHandleResult processMessage(const QAmqpMessage& message);
|
||||||
bool validateEvent(const EventData& event);
|
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);
|
void processHistoricalResponse(const QByteArray& data);
|
||||||
//QNetworkRequest createHistoricalRequest(const QUrl& url);
|
//QNetworkRequest createHistoricalRequest(const QUrl& url);
|
||||||
//事件确认
|
//事件确认
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,14 @@
|
||||||
#define MEASUREMENTDATAMANAGER_H
|
#define MEASUREMENTDATAMANAGER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
class QSettings;
|
class QSettings;
|
||||||
class QNetworkAccessManager;
|
class QNetworkAccessManager;
|
||||||
class QNetworkReply;
|
class QNetworkReply;
|
||||||
class WebSocketClient;
|
class WebSocketClient;
|
||||||
|
class MeasurementData;
|
||||||
|
|
||||||
class MeasurementDataManager : public QObject
|
class MeasurementDataManager : public QObject
|
||||||
{
|
{
|
||||||
|
|
@ -20,9 +24,11 @@ public:
|
||||||
void addSubscriptionData(const QStringList& measurements);
|
void addSubscriptionData(const QStringList& measurements);
|
||||||
void removeSubscriptionData(const QStringList& measurements);
|
void removeSubscriptionData(const QStringList& measurements);
|
||||||
void getSubscriptionRealtimeData();
|
void getSubscriptionRealtimeData();
|
||||||
|
void queryHistoricalEvents(const QString& dataID, const QDateTime& startTime, const QDateTime& endTime, const QString& step, const QString& type = "phasor");
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onReciveRealtimeData(const QString& dataMsg);
|
void onReceiveRealtimeData(const QString& dataMsg);
|
||||||
|
void onHistoricalRequestFinished(const QString& dataID, QNetworkReply* reply);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct RealtimeConfig
|
struct RealtimeConfig
|
||||||
|
|
@ -44,8 +50,7 @@ private:
|
||||||
|
|
||||||
struct HistoricalConfig
|
struct HistoricalConfig
|
||||||
{
|
{
|
||||||
QString host;
|
QUrl baseUrl;
|
||||||
int port;
|
|
||||||
int timeout; //请求超时(毫秒)
|
int timeout; //请求超时(毫秒)
|
||||||
int maxRetries; //最大重试次数
|
int maxRetries; //最大重试次数
|
||||||
int retryInterval; //重试间隔
|
int retryInterval; //重试间隔
|
||||||
|
|
@ -69,6 +74,8 @@ private:
|
||||||
void initialize();
|
void initialize();
|
||||||
void buildSubscriptionRequest(const QString& action, const QStringList& measurements);
|
void buildSubscriptionRequest(const QString& action, const QStringList& measurements);
|
||||||
void processSubscriptionResponse(const QString& action, QNetworkReply* reply);
|
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;
|
ServiceConfig m_serviceConfig;
|
||||||
|
|
@ -80,6 +87,9 @@ private:
|
||||||
QString m_clientID;
|
QString m_clientID;
|
||||||
QNetworkAccessManager* m_networkManager;
|
QNetworkAccessManager* m_networkManager;
|
||||||
WebSocketClient* m_webSocketClient;
|
WebSocketClient* m_webSocketClient;
|
||||||
|
|
||||||
|
//数据缓存
|
||||||
|
QHash<QString, QSharedPointer<MeasurementData>> m_dataCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,4 @@ httpPath=monitors/data/subscriptions
|
||||||
websocketPath=monitors/data/realtime/stream
|
websocketPath=monitors/data/realtime/stream
|
||||||
|
|
||||||
[HistoricalData]
|
[HistoricalData]
|
||||||
host=192.168.46.100
|
baseUrl=http://192.168.46.30:8888/api/points
|
||||||
port=10080
|
|
||||||
|
|
@ -68,7 +68,7 @@ void AlarmEventDataService::initialize()
|
||||||
m_config.rabbitMQConfig.heartbeat = m_settings->value("RabbitMQConfig/heartbeat").toInt();
|
m_config.rabbitMQConfig.heartbeat = m_settings->value("RabbitMQConfig/heartbeat").toInt();
|
||||||
m_config.rabbitMQConfig.autoAck = m_settings->value("RabbitMQConfig/autoAck").toBool();
|
m_config.rabbitMQConfig.autoAck = m_settings->value("RabbitMQConfig/autoAck").toBool();
|
||||||
//HistoricalDataConfig
|
//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.timeout = m_settings->value("HistoricalDataConfig/timeout").toInt();
|
||||||
m_config.historicalConfig.maxRetries = m_settings->value("HistoricalDataConfig/maxRetries").toInt();
|
m_config.historicalConfig.maxRetries = m_settings->value("HistoricalDataConfig/maxRetries").toInt();
|
||||||
m_config.historicalConfig.retryInterval = m_settings->value("HistoricalDataConfig/retryInterval").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)
|
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;
|
//QUrl url = m_config.historicalConfig.baseUrl;
|
||||||
if(!url.isValid())
|
if(!url.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
@ -251,7 +251,7 @@ bool AlarmEventDataService::validateEvent(const EventData& event)
|
||||||
return true;
|
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;
|
QUrl url = m_config.historicalConfig.baseUrl;
|
||||||
QUrlQuery query;
|
QUrlQuery query;
|
||||||
|
|
@ -276,6 +276,7 @@ void AlarmEventDataService::processHistoricalResponse(const QByteArray& data)
|
||||||
.arg(parseError.errorString())
|
.arg(parseError.errorString())
|
||||||
.arg(parseError.offset);
|
.arg(parseError.offset);
|
||||||
emit historicalQueryError(errorMsg);
|
emit historicalQueryError(errorMsg);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!doc.isObject())
|
if(!doc.isObject())
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ MeasurementDataManager::MeasurementDataManager()
|
||||||
, m_webSocketClient(new WebSocketClient(this))
|
, m_webSocketClient(new WebSocketClient(this))
|
||||||
{
|
{
|
||||||
initialize();
|
initialize();
|
||||||
connect(m_webSocketClient, &WebSocketClient::dataReceived, this, &MeasurementDataManager::onReciveRealtimeData);
|
connect(m_webSocketClient, &WebSocketClient::dataReceived, this, &MeasurementDataManager::onReceiveRealtimeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
MeasurementDataManager::~MeasurementDataManager()
|
MeasurementDataManager::~MeasurementDataManager()
|
||||||
|
|
@ -49,8 +49,7 @@ void MeasurementDataManager::initialize()
|
||||||
m_serviceConfig.realtimeCfg.httpPath = m_settings->value("RealtimeData/httpPath").toString();
|
m_serviceConfig.realtimeCfg.httpPath = m_settings->value("RealtimeData/httpPath").toString();
|
||||||
m_serviceConfig.realtimeCfg.websocketPath = m_settings->value("RealtimeData/websocketPath").toString();
|
m_serviceConfig.realtimeCfg.websocketPath = m_settings->value("RealtimeData/websocketPath").toString();
|
||||||
|
|
||||||
m_serviceConfig.historicalCfg.host = m_settings->value("HistoricalData/host").toString();
|
m_serviceConfig.historicalCfg.baseUrl = m_settings->value("HistoricalData/baseUrl").toUrl();
|
||||||
m_serviceConfig.historicalCfg.port = m_settings->value("HistoricalData/port").toInt();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -209,6 +208,71 @@ void MeasurementDataManager::processSubscriptionResponse(const QString& action,
|
||||||
reply->deleteLater();
|
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()
|
void MeasurementDataManager::getSubscriptionRealtimeData()
|
||||||
{
|
{
|
||||||
if(m_clientID.isEmpty())
|
if(m_clientID.isEmpty())
|
||||||
|
|
@ -221,12 +285,28 @@ void MeasurementDataManager::getSubscriptionRealtimeData()
|
||||||
QUrl url(strUrl);
|
QUrl url(strUrl);
|
||||||
if(!m_webSocketClient->connectToServer(url))
|
if(!m_webSocketClient->connectToServer(url))
|
||||||
{
|
{
|
||||||
QString errorMsg = QString("Connect to WebSocketServer failed.");
|
QString errorMsg = QString("Connect to WebSocketServer failed");
|
||||||
LOG_ERROR("WebSocket", errorMsg);
|
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;
|
QJsonParseError parseError;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(dataMsg.toUtf8(), &parseError);
|
QJsonDocument doc = QJsonDocument::fromJson(dataMsg.toUtf8(), &parseError);
|
||||||
|
|
@ -251,19 +331,28 @@ void MeasurementDataManager::onReciveRealtimeData(const QString& dataMsg)
|
||||||
|
|
||||||
QJsonObject targetObj = targetValue.toObject();
|
QJsonObject targetObj = targetValue.toObject();
|
||||||
QString dataID = targetObj.value("id").toString();
|
QString dataID = targetObj.value("id").toString();
|
||||||
|
QSharedPointer<MeasurementData> measurementData;
|
||||||
|
if(m_dataCache.contains(dataID))
|
||||||
|
measurementData = m_dataCache.value(dataID);
|
||||||
|
|
||||||
QJsonValue datasValue = targetObj.value("datas");
|
QJsonValue datasValue = targetObj.value("datas");
|
||||||
if(datasValue.isArray())
|
if(datasValue.isArray())
|
||||||
{
|
{
|
||||||
QJsonArray datasArray = datasValue.toArray();
|
QJsonArray datasArray = datasValue.toArray();
|
||||||
|
QVector<MeasurementDataPoint> dataPoints;
|
||||||
|
dataPoints.reserve(datasArray.size());
|
||||||
for(const QJsonValue& dataValue : std::as_const(datasArray))
|
for(const QJsonValue& dataValue : std::as_const(datasArray))
|
||||||
{
|
{
|
||||||
if(!dataValue.isObject())
|
if(!dataValue.isObject())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QJsonObject dataObj = dataValue.toObject();
|
QJsonObject dataObj = dataValue.toObject();
|
||||||
QString timestamp = dataObj.value("time").toString();
|
qint64 timestamp = dataObj.value("time").toString().toLongLong();
|
||||||
QString value = dataObj.value("value").toString();
|
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);
|
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();
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1256</width>
|
<width>1424</width>
|
||||||
<height>773</height>
|
<height>890</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
|
|
@ -148,7 +148,7 @@ icon: url(:/images/icon_event.png);
|
||||||
}
|
}
|
||||||
QPushButton:hover
|
QPushButton:hover
|
||||||
{
|
{
|
||||||
background-color: rgb(55,131,204);
|
background-color: rgba(55,131,204,200);
|
||||||
}
|
}
|
||||||
QPushButton:pressed
|
QPushButton:pressed
|
||||||
{
|
{
|
||||||
|
|
@ -184,10 +184,10 @@ background-color: rgb(67,160,249);
|
||||||
font: 700 12pt "微软雅黑";
|
font: 700 12pt "微软雅黑";
|
||||||
color:rgb(250,250,250);
|
color:rgb(250,250,250);
|
||||||
text-align:right;
|
text-align:right;
|
||||||
padding-right:35px;
|
|
||||||
background-color: rgb(64, 182, 113);
|
|
||||||
icon-size:20px;
|
icon-size:20px;
|
||||||
icon: url(:/images/icon_add.png);
|
icon: url(:/images/icon_add.png);
|
||||||
|
padding-right:35px;
|
||||||
|
background-color: rgb(64, 182, 113);
|
||||||
}
|
}
|
||||||
QPushButton:hover
|
QPushButton:hover
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue