380 lines
11 KiB
C++
380 lines
11 KiB
C++
#include "rpc_finsTcp.h"
|
|
#include "qprocess.h"
|
|
#include <QHostAddress>
|
|
#include <QVariant>
|
|
#include <QDebug>
|
|
|
|
#include <QTcpSocket>
|
|
#include <QJsonObject>
|
|
#include <QJsonDocument>
|
|
#include <windows.h>
|
|
static QProcess* process = nullptr;
|
|
static HANDLE jobHandle = nullptr;
|
|
rpc_finsTcp* create()
|
|
{
|
|
qDebug() << "rpc_finsTcp create success!";
|
|
return new rpc_finsTcp;
|
|
}
|
|
|
|
void destory(rpc_finsTcp* ptr)
|
|
{
|
|
|
|
if (ptr)
|
|
{
|
|
delete ptr;
|
|
ptr = nullptr;
|
|
}
|
|
qDebug() << " rpc_finsTcp destory success!";
|
|
}
|
|
bool ifRun = true;
|
|
rpc_finsTcp::rpc_finsTcp()
|
|
{
|
|
ifRun = true;
|
|
}
|
|
bool m_IsFinsTcp = false;
|
|
rpc_finsTcp::~rpc_finsTcp()
|
|
{
|
|
|
|
qDebug() << " ~rpc_finsTcp success!";
|
|
}
|
|
QQueue<QByteArray> readDataQueue;
|
|
// 从类中读数据到实例对象
|
|
QByteArray variantListToByteArray(const QVariant& var) {
|
|
QByteArray byteArray;
|
|
|
|
if (var.canConvert<QVariantList>()) {
|
|
QVariantList list = var.toList();
|
|
byteArray.reserve(list.size());
|
|
|
|
for (const QVariant& item : list) {
|
|
// 每个元素转为 uchar 存入 QByteArray
|
|
byteArray.append(static_cast<char>(item.toInt()));
|
|
}
|
|
}
|
|
|
|
return byteArray;
|
|
}
|
|
bool rpc_finsTcp::readData(std::vector<cv::Mat>& vec_mat, QByteArray& data)
|
|
{
|
|
JsonRpcClient* ptr = read_JsonRpcClient[data];
|
|
if(ptr == nullptr) {
|
|
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");
|
|
return true;
|
|
}
|
|
bool ifRetryCMD = false;
|
|
// 实例对象把数据写入到类
|
|
|
|
void startProcess(const QString& exePath) {
|
|
if (process) return; // 避免重复启动
|
|
|
|
process = new QProcess();
|
|
process->setProgram(exePath);
|
|
process->start();
|
|
|
|
if (!process->waitForStarted(1000)) {
|
|
qDebug() << "Process failed to start.";
|
|
delete process;
|
|
process = nullptr;
|
|
return;
|
|
}
|
|
|
|
DWORD pid = process->processId();
|
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
|
|
|
|
jobHandle = CreateJobObject(nullptr, nullptr);
|
|
if (jobHandle == nullptr) {
|
|
qDebug() << "Failed to create job object";
|
|
return;
|
|
}
|
|
|
|
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {};
|
|
jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
|
|
SetInformationJobObject(jobHandle, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli));
|
|
|
|
if (!AssignProcessToJobObject(jobHandle, hProcess)) {
|
|
qDebug() << "Failed to assign process to job object";
|
|
}
|
|
|
|
CloseHandle(hProcess);
|
|
}
|
|
|
|
void stopProcess() {
|
|
if (process) {
|
|
if (process->state() == QProcess::Running) {
|
|
process->kill();
|
|
process->waitForFinished(500);
|
|
}
|
|
delete process;
|
|
process = nullptr;
|
|
}
|
|
|
|
if (jobHandle) {
|
|
CloseHandle(jobHandle);
|
|
jobHandle = nullptr;
|
|
}
|
|
}
|
|
bool rpc_finsTcp::writeData(std::vector<cv::Mat>& vec_mat, QByteArray& data){
|
|
QList<QByteArray> m_list = data.split('_');
|
|
if (m_list.size() < 4)
|
|
{
|
|
qCritical() << data + " m_list.size() != 4;command err";
|
|
return false;
|
|
}
|
|
QString m_value = m_list.at(3);
|
|
QString commond = m_list.at(0);
|
|
if (commond == "init") {
|
|
m_IP = m_list.at(1);
|
|
m_port = m_list.at(2).toInt();
|
|
|
|
}
|
|
else if(data.contains("read")) {
|
|
readDataQueue.append(data);
|
|
}
|
|
else {
|
|
if(data.contains("Heart") == false)
|
|
qDebug() << data;
|
|
emit writeCallSignal("excuteCli", QJsonArray{ QString(data) }, "finstcp");
|
|
//
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool rpc_finsTcp::initParas(QByteArray& data){
|
|
|
|
startProcess("./json_rpc_server.exe");
|
|
subThread = new QThread(this);
|
|
write_JsonRpcClient = new JsonRpcClientWorker();
|
|
write_JsonRpcClient->moveToThread(subThread);
|
|
|
|
QObject::connect(this, &rpc_finsTcp::initRpcClient,
|
|
write_JsonRpcClient, &JsonRpcClientWorker::initClient, Qt::QueuedConnection);
|
|
emit initRpcClient();
|
|
|
|
QObject::connect(this, &rpc_finsTcp::writeCallSignal,
|
|
write_JsonRpcClient, &JsonRpcClientWorker::writeCallSlot,Qt::QueuedConnection);
|
|
subThread->start();
|
|
|
|
emit writeCallSignal("init", QJsonArray{ m_IP,m_port }, "finstcp");
|
|
while (write_JsonRpcClient->connection == None)
|
|
QThread::msleep(1);
|
|
|
|
if (write_JsonRpcClient->connection == Disconnected) {
|
|
qDebug() << "JsonRpcClientSubThread connection failed!";
|
|
return false;
|
|
}
|
|
else if (write_JsonRpcClient->connection == Connected) {
|
|
qDebug() << "JsonRpcClientSubThread connected successfully!";
|
|
}
|
|
//qDebug() << "返回结果:" << result;
|
|
|
|
//QList<QPair<QString, QJsonObject>> batchList;
|
|
//batchList << qMakePair(QString("read_short"), params)
|
|
// << qMakePair(QString("read_bit"), QJsonObject{ {"bit", "M0"} });
|
|
|
|
//QJsonArray resultArray = _JsonRpcClient->batchCall(batchList);
|
|
//qDebug() << "批量结果:" << resultArray;
|
|
return true;
|
|
|
|
}
|
|
|
|
bool rpc_finsTcp::run()
|
|
{
|
|
// 没有用到
|
|
//qDebug() << "[info] " << __FUNCTION__ << " line:" << __LINE__ << " success!";
|
|
return true;
|
|
}
|
|
|
|
|
|
JsonRpcClient::JsonRpcClient(const QString& host, quint16 port)
|
|
:host_(host), port_(port), idCounter_(1) {
|
|
|
|
socket_.connectToHost(host_, port_);
|
|
if (!socket_.waitForConnected(3000)) {
|
|
qWarning() << "[JsonRpcClient] Initial connection failed:" << socket_.errorString();
|
|
_connectionStatus = Disconnected;
|
|
}
|
|
else {
|
|
qDebug() << "[JsonRpcClient] Connected to" << host_ << ":" << port_;
|
|
_connectionStatus = Connected;
|
|
}
|
|
}
|
|
|
|
bool JsonRpcClient::reconnect() {
|
|
if (socket_.state() == QAbstractSocket::ConnectedState) {
|
|
return true;
|
|
}
|
|
|
|
socket_.abort(); // 清理旧连接
|
|
socket_.connectToHost(host_, port_);
|
|
if (socket_.waitForConnected(3000)) {
|
|
qDebug() << "[JsonRpcClient] Reconnected successfully.";
|
|
return true;
|
|
}
|
|
else {
|
|
qWarning() << "[JsonRpcClient] Reconnection failed:" << socket_.errorString();
|
|
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{
|
|
{"jsonrpc", "2.0"},
|
|
{"method", method},
|
|
{"params", params},
|
|
{"id", idCounter_++}
|
|
};
|
|
if (!module.isEmpty()) {
|
|
request["module"] = module;
|
|
}
|
|
|
|
QJsonDocument doc(request);
|
|
QByteArray data = doc.toJson(QJsonDocument::Compact);
|
|
|
|
if (socket_.write(data) == -1 || !socket_.waitForBytesWritten(1000)) {
|
|
qWarning() << "[JsonRpcClient] Write failed:" << socket_.errorString();
|
|
return;
|
|
}
|
|
} |