// HttpAdapter.cpp #include "httpChannel.h" #include #include #include #include #include #include #include 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"; } }