DiagramDesigner/diagramCommunication/source/httpAdapter.cpp

261 lines
7.5 KiB
C++
Raw Normal View History

2025-12-12 17:46:37 +08:00
// HttpAdapter.cpp
#include "httpChannel.h"
#include <QNetworkRequest>
#include <QNetworkProxy>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QTimer>
#include <QDebug>
HttpAdapter::HttpAdapter(const ChannelConfig& config, QObject* parent)
: CommunicationChannel(config, parent)
, m_networkManager(new QNetworkAccessManager(this))
{
// 配置SSL
if (m_config.sslConfig.isNull()) {
QSslConfiguration sslConfig = QSslConfiguration::defaultConfiguration();
sslConfig.setPeerVerifyMode(QSslSocket::VerifyNone);
m_config.sslConfig = sslConfig;
}
// 连接信号
connect(m_networkManager, &QNetworkAccessManager::authenticationRequired,
this, &HttpAdapter::onAuthenticationRequired);
qDebug() << "HttpAdapter created for" << m_config.channelId;
}
HttpAdapter::~HttpAdapter()
{
// 取消所有未完成的请求
for (auto reply : m_pendingRequests.keys()) {
reply->abort();
reply->deleteLater();
}
m_pendingRequests.clear();
}
bool HttpAdapter::connectToHost()
{
// HTTP协议无需建立持久连接只需验证端点是否可达
if (m_config.endpoint.isEmpty() || !m_config.endpoint.isValid()) {
emit errorOccurred("Invalid endpoint URL: " + m_config.endpoint.toString());
return false;
}
// 发送一个测试请求验证连接
HttpRequest testRequest;
testRequest.method = GET;
QNetworkRequest request(m_config.endpoint);
request.setSslConfiguration(m_config.sslConfig);
request.setRawHeader("User-Agent", "PowerSCADA/1.0");
QNetworkReply* reply = m_networkManager->get(request);
connect(reply, &QNetworkReply::finished,
this, [this, reply]() {
onReplyFinished(reply);
});
m_pendingRequests.insert(reply, testRequest);
// 设置超时
QTimer::singleShot(m_config.timeout, this, [this, reply]() {
if (reply && reply->isRunning()) {
reply->abort();
emit errorOccurred("Connection timeout");
}
});
emit connected();
return true;
}
bool HttpAdapter::disconnectFromHost()
{
// 取消所有未完成的请求
for (auto reply : m_pendingRequests.keys()) {
reply->abort();
reply->deleteLater();
}
m_pendingRequests.clear();
emit disconnected();
return true;
}
bool HttpAdapter::sendData(const QByteArray& data)
{
HttpRequest request;
request.method = POST;
request.data = data;
request.contentType = "application/octet-stream";
return sendRequest(request);
}
bool HttpAdapter::isConnected() const
{
// HTTP是无状态协议总是返回true表示可以发送请求
return m_config.endpoint.isValid();
}
bool HttpAdapter::sendRequest(const HttpRequest& request)
{
if (!m_config.endpoint.isValid()) {
emit errorOccurred("Invalid endpoint URL");
return false;
}
QNetworkRequest networkRequest(m_config.endpoint);
networkRequest.setSslConfiguration(m_config.sslConfig);
networkRequest.setRawHeader("User-Agent", "PowerSCADA/1.0");
networkRequest.setRawHeader("Content-Type", request.contentType.toUtf8());
// 添加自定义头
for (auto it = request.headers.begin(); it != request.headers.end(); ++it) {
networkRequest.setRawHeader(it.key().toUtf8(), it.value().toUtf8());
}
QNetworkReply* reply = nullptr;
switch (request.method) {
case GET:
reply = m_networkManager->get(networkRequest);
break;
case POST:
reply = m_networkManager->post(networkRequest, request.data);
break;
case PUT:
reply = m_networkManager->put(networkRequest, request.data);
break;
case DELETE:
reply = m_networkManager->deleteResource(networkRequest);
break;
default:
emit errorOccurred("Unsupported HTTP method");
return false;
}
if (!reply) {
emit errorOccurred("Failed to create network request");
return false;
}
// 设置请求超时
QTimer* timeoutTimer = new QTimer(this);
timeoutTimer->setSingleShot(true);
connect(timeoutTimer, &QTimer::timeout, this, [this, reply]() {
if (reply && reply->isRunning()) {
reply->abort();
emit errorOccurred("Request timeout");
}
});
timeoutTimer->start(m_config.timeout);
connect(reply, &QNetworkReply::finished, this, [this, reply, timeoutTimer]() {
timeoutTimer->stop();
timeoutTimer->deleteLater();
onReplyFinished(reply);
});
m_pendingRequests.insert(reply, request);
return true;
}
void HttpAdapter::setAuthentication(const QString& username, const QString& password)
{
m_username = username;
m_password = password;
}
void HttpAdapter::setProxy(const QNetworkProxy& proxy)
{
m_networkManager->setProxy(proxy);
}
bool HttpAdapter::readDataPoints(const QStringList& pointIds)
{
QJsonObject requestObj;
requestObj["command"] = "read";
requestObj["points"] = QJsonArray::fromStringList(pointIds);
requestObj["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
HttpRequest request;
request.method = POST;
request.data = QJsonDocument(requestObj).toJson();
request.contentType = "application/json";
return sendRequest(request);
}
bool HttpAdapter::writeDataPoint(const QString& pointId, const QVariant& value)
{
QJsonObject requestObj;
requestObj["command"] = "write";
requestObj["point"] = pointId;
requestObj["value"] = QJsonValue::fromVariant(value);
requestObj["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
HttpRequest request;
request.method = POST;
request.data = QJsonDocument(requestObj).toJson();
request.contentType = "application/json";
return sendRequest(request);
}
bool HttpAdapter::sendControlCommand(const QString& deviceId, int command, const QVariant& param)
{
QJsonObject requestObj;
requestObj["command"] = "control";
requestObj["device"] = deviceId;
requestObj["cmd"] = command;
requestObj["param"] = QJsonValue::fromVariant(param);
requestObj["timestamp"] = QDateTime::currentDateTime().toString(Qt::ISODate);
HttpRequest request;
request.method = POST;
request.data = QJsonDocument(requestObj).toJson();
request.contentType = "application/json";
return sendRequest(request);
}
void HttpAdapter::onReplyFinished(QNetworkReply* reply)
{
if (!reply || !m_pendingRequests.contains(reply)) {
return;
}
auto request = m_pendingRequests.take(reply);
if (reply->error() != QNetworkReply::NoError) {
QString errorMsg = QString("HTTP error: %1 - %2")
.arg(reply->error())
.arg(reply->errorString());
emit errorOccurred(errorMsg);
} else {
QByteArray responseData = reply->readAll();
emit dataReceived(responseData);
// 记录日志
qDebug() << "HTTP response received:" << reply->url().toString()
<< "Status:" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()
<< "Size:" << responseData.size() << "bytes";
}
reply->deleteLater();
}
void HttpAdapter::onAuthenticationRequired(QNetworkReply* reply, QAuthenticator* authenticator)
{
if (!m_username.isEmpty() && !m_password.isEmpty()) {
authenticator->setUser(m_username);
authenticator->setPassword(m_password);
} else {
qWarning() << "Authentication required but no credentials provided";
}
}