PowerMaster/source/measurementDataUtils.cpp

155 lines
4.2 KiB
C++

#include "measurementDataUtils.h"
#include "logger.h"
#include <QTimer>
#include <QRandomGenerator>
WebSocketClient::WebSocketClient(QObject* parent)
: QObject(parent)
, m_webSocket(nullptr)
, m_connected(false)
, m_connectionStatus(ConnectionStatus::Disconnected)
, m_reconnectTimer(new QTimer(this))
, m_reconnectInterval(5000) //默认5秒重连
, m_reconnectAttempts(0)
, m_maxReconnectAttempts(10) //默认最多重连10次
{
setupWebSocket();
m_reconnectTimer->setSingleShot(true);
connect(m_reconnectTimer, &QTimer::timeout, this, &WebSocketClient::onReconnectTimeout);
}
WebSocketClient::~WebSocketClient()
{
disconnectFromServer();
cleanupWebSocket();
}
bool WebSocketClient::connectToServer(const QUrl& url)
{
if(!url.isValid())
{
QString errorMsg = QString("Invalid server URL: %1").arg(url.toString());
LOG_ERROR("WebSocket", errorMsg);
return false;
}
//if(m_webSocket && (m_webSocket->state() == QAbstractSocket::ConnectedState || m_webSocket->state() == QAbstractSocket::ConnectingState))
if(m_connectionStatus == ConnectionStatus::Connecting || m_connectionStatus == ConnectionStatus::Connected)
return true;
m_serverUrl = url;
m_connectionStatus = ConnectionStatus::Connecting;
if(!m_webSocket)
setupWebSocket();
m_webSocket->open(url);
return true;
}
void WebSocketClient::disconnectFromServer()
{
if(m_webSocket)
{
m_webSocket->close();
m_connected = false;
m_connectionStatus = ConnectionStatus::Disconnected;
resetReconnect();
}
}
void WebSocketClient::setReconnectInterval(int intervalMs)
{
if(intervalMs > 0 && intervalMs != m_reconnectInterval)
m_reconnectInterval = intervalMs;
}
void WebSocketClient::setMaxReconnectAttempts(int maxAttempts)
{
if(maxAttempts >=0 && maxAttempts != m_maxReconnectAttempts)
m_maxReconnectAttempts = maxAttempts;
}
void WebSocketClient::setupWebSocket()
{
cleanupWebSocket();
m_webSocket = new QWebSocket();
connect(m_webSocket, &QWebSocket::connected, this, &WebSocketClient::onConnected);
connect(m_webSocket, &QWebSocket::disconnected, this, &WebSocketClient::onDisconnected);
connect(m_webSocket, &QWebSocket::errorOccurred, this, &WebSocketClient::onError);
connect(m_webSocket, &QWebSocket::textMessageReceived, this, &WebSocketClient::onTextMessageReceived);
}
void WebSocketClient::cleanupWebSocket()
{
if(m_webSocket)
{
m_webSocket->disconnected();
m_webSocket->deleteLater();
m_webSocket = nullptr;
}
}
void WebSocketClient::scheduleReconnect()
{
if(m_connectionStatus == ConnectionStatus::Disconnected || m_connectionStatus == ConnectionStatus::Error)
return;
if(m_reconnectAttempts < m_maxReconnectAttempts)
{
int delay = m_reconnectInterval * (1 /*<< m_reconnectAttempts*/);// 指数退避,<<n相当于乘以2的n次方
// 添加随机抖动避免多个客户端同时重连
/*int jitter = QRandomGenerator::global()->bounded(0, 1000);
delay += jitter;
// 限制最大延迟为5分钟
delay = qMin(delay, 300000);*/
m_reconnectTimer->start(delay);
m_reconnectAttempts++;
m_connectionStatus = ConnectionStatus::Reconncting;
}
}
void WebSocketClient::resetReconnect()
{
if(m_reconnectTimer->isActive())
m_reconnectTimer->stop();
m_reconnectAttempts = 0;
}
///槽函数
void WebSocketClient::onConnected()
{
m_connected = true;
m_connectionStatus = ConnectionStatus::Connected;
resetReconnect();
}
void WebSocketClient::onDisconnected()
{
m_connected = false;
m_connectionStatus = ConnectionStatus::Disconnected;
scheduleReconnect();
}
void WebSocketClient::onError(QAbstractSocket::SocketError error)
{
QString errorMsg = m_webSocket ? m_webSocket->errorString() : "Unknown WebSocket error";
LOG_ERROR("WebSocket", errorMsg);
scheduleReconnect();
}
void WebSocketClient::onTextMessageReceived(const QString& message)
{
emit dataReceived(message);
}
void WebSocketClient::onReconnectTimeout()
{
if(!m_webSocket)
setupWebSocket();
m_webSocket->open(m_serverUrl);
}