优化相机模块,优化rpc模块

This commit is contained in:
2025-09-03 15:37:40 +08:00
parent 22e6be7afb
commit 142c41da77
14 changed files with 459 additions and 394 deletions
+155 -148
View File
@@ -8,6 +8,23 @@
#include <QJsonObject>
#include <QJsonDocument>
#include <windows.h>
#include <QDateTime>
#include <QCoreApplication>
#include <QThread>
#include <QTimer>
#include <QCryptographicHash>
#include <QScopedPointer>
#include <QBuffer>
#include <QPointer>
#include <QRegularExpression>
#include <QDataStream>
#include <QElapsedTimer>
#include <QMutexLocker>
#include <algorithm>
#include <memory>
#include <cmath>
#include <cstring>
static QProcess* process = nullptr;
static HANDLE jobHandle = nullptr;
rpc_finsTcp* create()
@@ -61,9 +78,8 @@ bool rpc_finsTcp::readData(std::vector<cv::Mat>& vec_mat, QByteArray& data)
ptr = new JsonRpcClient("127.0.0.1", 9000);
read_JsonRpcClient[data] = ptr;
}
//auto result = read_JsonRpcClient[data]->call("excuteCli", QJsonArray{ QString(data) }, "finstcp");
//data = variantListToByteArray(result);
data = ptr->finsReadCall("excuteCli", QString(data), "finstcp");
QByteArray resp = ptr->finsReadCall("excuteCli", QString(data), "finstcp");
data = resp; // 已是解码后的原始字节
return true;
}
bool ifRetryCMD = false;
@@ -136,6 +152,8 @@ bool rpc_finsTcp::writeData(std::vector<cv::Mat>& vec_mat, QByteArray& data){
readDataQueue.append(data);
}
else {
if (data.contains("null"))
return true;
if(data.contains("Heart") == false)
qDebug() << data;
emit writeCallSignal("excuteCli", QJsonArray{ QString(data) }, "finstcp");
@@ -146,7 +164,7 @@ bool rpc_finsTcp::writeData(std::vector<cv::Mat>& vec_mat, QByteArray& data){
bool rpc_finsTcp::initParas(QByteArray& data){
startProcess("./json_rpc_server.exe");
startProcess("./json_rpc_server_1_1_0.exe");
subThread = new QThread(this);
write_JsonRpcClient = new JsonRpcClientWorker();
write_JsonRpcClient->moveToThread(subThread);
@@ -220,161 +238,150 @@ bool JsonRpcClient::reconnect() {
return false;
}
}
QVariant jsonToVariant(const nlohmann::json& j)
{
if (j.is_null()) return QVariant();
if (j.is_boolean()) return j.get<bool>();
if (j.is_number_integer()) return j.get<qint64>();
if (j.is_number_unsigned()) return static_cast<quint64>(j.get<std::uint64_t>());
if (j.is_number_float()) return j.get<double>();
if (j.is_string()) return QString::fromStdString(j.get<std::string>());
if (j.is_array()) {
QVariantList list;
for (const auto& el : j) list.append(jsonToVariant(el));
return list;
}
if (j.is_object()) {
QVariantMap map;
for (auto it = j.begin(); it != j.end(); ++it)
map[QString::fromStdString(it.key())] = jsonToVariant(it.value());
return map;
}
return QVariant(); // fallback
}
QVariant JsonRpcClient::call(const QString& method, const QJsonArray& params, const QString& module)
{
QMutexLocker locker(&mutex_);
if (socket_.state() != QAbstractSocket::ConnectedState) {
qWarning() << "[JsonRpcClient] Socket not connected.";
if (!reconnect()) return QVariant();
}
QString reqStr = QString(R"({"jsonrpc":"2.0","method":"%1","params":%2,"id":%3)")
.arg(method)
.arg(QString::fromUtf8(QJsonDocument(params).toJson(QJsonDocument::Compact)))
.arg(idCounter_++);
if (!module.isEmpty()) {
reqStr += QString(R"(,"module":"%1")").arg(module);
}
reqStr += "}";
if (socket_.write(reqStr.toUtf8()) == -1 || !socket_.waitForBytesWritten(1000)) {
qWarning() << "[JsonRpcClient] Write failed.";
return QVariant();
}
if (!socket_.waitForReadyRead(10000)) {
qWarning() << "[JsonRpcClient] Read timeout.";
return QVariant();
}
QByteArray responseData = socket_.readAll();
// 使用 nlohmann json 替代 Qt 解析
try {
auto respJson = nlohmann::json::parse(responseData.constData(), responseData.constData() + responseData.size());
if (respJson.contains("error")) {
qWarning() << "[JsonRpcClient] Error:" << QString::fromStdString(respJson["error"].dump());
return QVariant();
}
return jsonToVariant(respJson["result"]);
}
catch (const nlohmann::json::parse_error& e) {
qWarning() << "[JsonRpcClient] Parse error:" << e.what();
return QVariant();
}
}
QByteArray JsonRpcClient::finsReadCall(const QString& method, const QString& params, const QString& module) {
QMutexLocker locker(&mutex_);
if (socket_.state() != QAbstractSocket::ConnectedState) {
qWarning() << "[JsonRpcClient] Socket not connected.";
if (!reconnect()) return QByteArray();
}
QString reqStr = QString(R"({"jsonrpc":"2.0","method":"%1","params":["%2"],"id":%3)")
.arg(method)
.arg(params)
.arg(idCounter_++);
if (!module.isEmpty()) {
reqStr += QString(R"(,"module":"%1")").arg(module);
}
reqStr += "}";
if (socket_.write(reqStr.toUtf8()) == -1 || !socket_.waitForBytesWritten(1000)) {
qWarning() << "[JsonRpcClient] Write failed.";
return QByteArray();
}
if (!socket_.waitForReadyRead(10000)) {
qWarning() << "[JsonRpcClient] Read timeout.";
return QByteArray();
}
QByteArray responseData = socket_.readAll();
// 仅用QByteArray查找和分割功能解析result数组
if (responseData.contains("error")) {
qWarning() << "[JsonRpcClient] Error in response:" << responseData;
return QByteArray();
}
// 查找 "result": [ 和对应的 ]
int resultPos = responseData.indexOf("\"result\"");
if (resultPos == -1) {
qWarning() << "[JsonRpcClient] No result field in response:" << responseData;
return QByteArray();
}
int arrayStart = responseData.indexOf('[', resultPos);
int arrayEnd = responseData.indexOf(']', arrayStart);
if (arrayStart == -1 || arrayEnd == -1 || arrayEnd <= arrayStart) {
qWarning() << "[JsonRpcClient] Result array not found or malformed:" << responseData;
return QByteArray();
}
QByteArray arrayContent = responseData.mid(arrayStart + 1, arrayEnd - arrayStart - 1);
// 按逗号分割
QList<QByteArray> items = arrayContent.split(',');
QByteArray result;
for (QByteArray item : items) {
item = item.trimmed();
bool ok = false;
int val = item.toInt(&ok);
if (ok) {
result.append(static_cast<char>(val));
} else if (!item.isEmpty()) {
qWarning() << "[JsonRpcClient] Non-integer value in result array:" << item;
return QByteArray();
}
}
return result;
}
void JsonRpcClient::writeCall(const QString& method, const QJsonArray& params, const QString& module) {
if (socket_.state() != QAbstractSocket::ConnectedState) {
qWarning() << "[JsonRpcClient] Socket not connected, trying to reconnect...";
if (!reconnect()) return;
}
QJsonObject request{
int myId = idCounter_++;
QJsonObject req{
{"jsonrpc", "2.0"},
{"method", method},
{"params", params},
{"id", idCounter_++}
{"id", myId}
};
if (!module.isEmpty()) {
request["module"] = module;
if (!module.isEmpty()) req.insert("module", module);
QJsonObject resp = sendRequestBuildAndAwait(req);
if (resp.contains("error")) {
qWarning() << "[JsonRpcClient] Error:" << QJsonDocument(resp["error"].toObject()).toJson(QJsonDocument::Compact);
return QVariant();
}
if (!resp.contains("result")) return QVariant();
QJsonValue r = resp.value("result");
if (r.isString()) return r.toString();
if (r.isDouble()) return r.toDouble();
if (r.isBool()) return r.toBool();
if (r.isArray()) return r.toArray().toVariantList();
if (r.isObject()) return r.toObject().toVariantMap();
return QVariant();
}
QByteArray JsonRpcClient::finsReadCall(const QString& method, const QString& params, const QString& module) {
QMutexLocker locker(&mutex_);
if (socket_.state() != QAbstractSocket::ConnectedState) {
if (!reconnect()) return QByteArray();
}
int myId = idCounter_++;
QJsonArray p; p.append(params);
QJsonObject req{{"jsonrpc","2.0"},{"method",method},{"params",p},{"id",myId}};
if (!module.isEmpty()) req.insert("module", module);
QJsonDocument doc(req);
QByteArray payload = doc.toJson(QJsonDocument::Compact);
if (socket_.write(payload) == -1 || !socket_.waitForBytesWritten(1000)) {
qWarning() << "[JsonRpcClient] Write failed.";
return QByteArray();
}
QJsonDocument doc(request);
QByteArray data = doc.toJson(QJsonDocument::Compact);
if (socket_.write(data) == -1 || !socket_.waitForBytesWritten(1000)) {
qWarning() << "[JsonRpcClient] Write failed:" << socket_.errorString();
return;
QJsonObject respObj;
if (!waitAndReadResponse(myId, respObj)) {
qWarning() << "[JsonRpcClient] Read timeout or parse error.";
return QByteArray();
}
if (respObj.contains("error")) {
qWarning() << "[JsonRpcClient] Error:" << QJsonDocument(respObj["error"].toObject()).toJson(QJsonDocument::Compact);
return QByteArray();
}
QString b64 = respObj.value("result").toString();
QByteArray decoded = QByteArray::fromBase64(b64.toUtf8());
return decoded;
}
QList<QByteArray> JsonRpcClient::extractJsonFrames(QByteArray& buffer) {
QList<QByteArray> frames;
int start = -1;
int braceDepth = 0;
bool inString = false;
char prev = 0;
for (int i = 0; i < buffer.size(); ++i) {
char c = buffer[i];
if (c == '"' && prev != '\\') inString = !inString;
if (!inString) {
if (c == '{') {
if (braceDepth == 0) start = i;
braceDepth++;
} else if (c == '}') {
braceDepth--;
if (braceDepth == 0 && start != -1) {
int len = i - start + 1;
frames.append(buffer.mid(start, len));
start = -1;
}
}
}
prev = c;
}
if (braceDepth == 0) {
if (!frames.isEmpty()) {
int lastEnd = buffer.lastIndexOf('}');
if (lastEnd != -1) buffer = buffer.mid(lastEnd + 1);
}
} else {
if (start > 0) buffer = buffer.mid(start);
}
return frames;
}
bool JsonRpcClient::waitAndReadResponse(int expectId, QJsonObject& outResp, int timeoutMs) {
QElapsedTimer timer; timer.start();
while (timer.elapsed() < timeoutMs) {
if (socket_.bytesAvailable() == 0) {
int remain = timeoutMs - (int)timer.elapsed();
if (!socket_.waitForReadyRead(qMin(remain, 1000))) {
continue;
}
}
QByteArray chunk = socket_.readAll();
if (!chunk.isEmpty()) recvBuffer_.append(chunk);
auto frames = extractJsonFrames(recvBuffer_);
for (const QByteArray& f : frames) {
QJsonParseError perr;
QJsonDocument jd = QJsonDocument::fromJson(f, &perr);
if (perr.error != QJsonParseError::NoError) {
qWarning() << "[JsonRpcClient] parse frame error:" << perr.errorString();
continue;
}
if (jd.isArray()) {
for (const QJsonValue& v : jd.array()) {
if (!v.isObject()) continue;
QJsonObject obj = v.toObject();
if (obj.value("id").toInt() == expectId) { outResp = obj; return true; }
}
} else if (jd.isObject()) {
QJsonObject obj = jd.object();
if (obj.value("id").toInt() == expectId) { outResp = obj; return true; }
}
}
}
return false;
}
QJsonObject JsonRpcClient::sendRequestBuildAndAwait(const QJsonObject& req, int timeoutMs) {
QByteArray payload = QJsonDocument(req).toJson(QJsonDocument::Compact);
int id = req.value("id").toInt();
if (socket_.write(payload) == -1 || !socket_.waitForBytesWritten(1000)) {
return QJsonObject{{"error", QJsonObject{{"code", -1},{"message", "write failed"}}}};
}
QJsonObject resp;
if (!waitAndReadResponse(id, resp, timeoutMs)) {
return QJsonObject{{"error", QJsonObject{{"code", -2},{"message", "timeout"}}}};
}
return resp;
}
void JsonRpcClient::writeCall(const QString& method, const QJsonArray& params, const QString& module) {
call(method, params, module);
}
+7 -5
View File
@@ -14,13 +14,12 @@
#include <QTimer>
#include <unordered_map>
#include <qjsonarray.h>
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonDocument>
#include <QHostAddress>
#include <qmap.h>
#include <qthread.h>
#include <nlohmannJson.hpp>
enum connectionStatus {
None,
Disconnected,
@@ -36,13 +35,16 @@ public:
QByteArray finsReadCall(const QString& method, const QString& params = "", const QString& module = QString());
bool reconnect(); // 主动重连,或 call() 失败时调用
private:
QMutex mutex_; // 确保线程安全
// 解析累计缓冲中的完整 JSON 帧(可能存在粘包/拆包)
QList<QByteArray> extractJsonFrames(QByteArray& buffer);
bool waitAndReadResponse(int expectId, QJsonObject& outResp, int timeoutMs = 8000);
QJsonObject sendRequestBuildAndAwait(const QJsonObject& req, int timeoutMs = 8000);
QMutex mutex_; // 确保线程安全
QTcpSocket socket_;
QString host_;
quint16 port_;
int idCounter_;
QByteArray recvBuffer_; // 累计接收缓冲
};
class JsonRpcClientWorker : public QObject {
Q_OBJECT