DiagramDesigner/diagramCommunication/source/httpAdapter.cpp

261 lines
7.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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";
}
}