V20251231-2.3.3
增加了rpcFIns的boos改版,在发送数据量较多时表现良好。(测试) 增加了存图时会将路径写入到单独的数据库中。(测试) 增加了chainWatcher用于监控线程是否异常退出或未启动。(测试) 在赢合预设中进站ng之类的会发送4到结果地址。 TextRendererZH类修改为可暂存需要绘画/打印的内容,并在需要的时候统一打印。 参数修改界面新增能隐藏预览中部分分类的功能。 优化程序结构。
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
1.初始化语句修改
|
||||
init_192.168.1.101_9600_12
|
||||
[ IP ][端口][线程数量]
|
||||
2.目前发送采用乱序多线程并发,如果需要有序发送需要按照以下放松
|
||||
2.1.强制指定某线程按顺序发送
|
||||
SAMPLE: write_D100_1_1 最后一个1为线程号,强制使用1号线程发送
|
||||
2.2.强制指定某线程按顺序发送
|
||||
SAMPLE: write_D100_1#write_D100_2#write_D100_3 强制将这几句按顺序在下一线程内按顺序发
|
||||
@@ -0,0 +1,473 @@
|
||||
#include "rpc_finsTcp.h"
|
||||
#include "qprocess.h"
|
||||
#include <QHostAddress>
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
|
||||
#include <QTcpSocket>
|
||||
#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>
|
||||
#include <atomic>
|
||||
|
||||
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() {
|
||||
|
||||
for (auto& client : write_JsonRpcClients) {
|
||||
if (client.first) {
|
||||
// 断开所有信号槽连接
|
||||
client.first->disconnect();
|
||||
|
||||
if (client.first->isRunning()) {
|
||||
client.first->quit();
|
||||
if (!client.first->wait(1000)) {
|
||||
qWarning() << "subThread quit timeout!";
|
||||
}
|
||||
}
|
||||
// 如果 subThread 没有 parent,则需要手动 delete
|
||||
//if (!subThread->parent()) {
|
||||
// delete subThread;
|
||||
//}
|
||||
//subThread = nullptr;
|
||||
}
|
||||
if (client.second) {
|
||||
delete client.second;
|
||||
client.second = nullptr;
|
||||
}
|
||||
}
|
||||
if (hearBeatThread) {
|
||||
// 断开所有信号槽连接
|
||||
hearBeatThread->disconnect();
|
||||
|
||||
if (hearBeatThread->isRunning()) {
|
||||
hearBeatThread->quit();
|
||||
if (!hearBeatThread->wait(1000)) {
|
||||
qWarning() << "subThread quit timeout!";
|
||||
}
|
||||
}
|
||||
// 如果 subThread 没有 parent,则需要手动 delete
|
||||
//if (!subThread->parent()) {
|
||||
// delete subThread;
|
||||
//}
|
||||
//subThread = nullptr;
|
||||
}
|
||||
if (hearBeatClinet) {
|
||||
delete hearBeatClinet;
|
||||
hearBeatClinet = nullptr;
|
||||
}
|
||||
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;
|
||||
}
|
||||
QByteArray resp = ptr->finsReadCall("excuteCli", QString(data), "finstcp");
|
||||
data = resp; // 已是解码后的原始字节
|
||||
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 commond = m_list.at(0);
|
||||
if (commond == "init") {
|
||||
m_IP = m_list.at(1);
|
||||
m_port = m_list.at(2).toInt();
|
||||
threadCount = m_list.at(3).toInt();
|
||||
}
|
||||
else if(data.contains("read")) {
|
||||
readDataQueue.append(data);
|
||||
}
|
||||
else {
|
||||
if (data.contains("null"))
|
||||
return true;
|
||||
if (data.contains("Heart") == true) {//专门的发送心跳线程去发送此数据
|
||||
emit writeCallSignal("excuteCli", QJsonArray{ QString(data) }, "finstcp", -1);
|
||||
return true;
|
||||
}
|
||||
//检查是不是复数命令
|
||||
QList<QByteArray> commands = data.split('#');
|
||||
|
||||
int threadIndex = -1;
|
||||
{
|
||||
QMutexLocker locker(&threadUseIndexMutex);
|
||||
threadIndex = threadUseIndex;
|
||||
if (++threadUseIndex >= write_JsonRpcClients.size()) threadUseIndex = 0;
|
||||
}
|
||||
for (auto& command : commands) {//分割命令
|
||||
QList<QByteArray> commandSplit = command.split('_');
|
||||
if (commandSplit.size() >= 5) {//如果是指定发送线程的
|
||||
QString sendData = command.left(command.lastIndexOf("_"));
|
||||
emit writeCallSignal("excuteCli", QJsonArray{ QString(sendData) }, "finstcp", m_list.at(4).toInt());
|
||||
}
|
||||
else {
|
||||
emit writeCallSignal("excuteCli", QJsonArray{ QString(command) }, "finstcp", threadIndex);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
}
|
||||
return true;
|
||||
}
|
||||
void rpc_finsTcp::initClientAndThread(std::pair<QThread*, JsonRpcClientWorker*>& pairData,const int& i) {
|
||||
pairData.first = new QThread();
|
||||
pairData.second = new JsonRpcClientWorker(i);
|
||||
pairData.second->moveToThread(pairData.first);
|
||||
|
||||
QObject::connect(this, &rpc_finsTcp::initRpcClient,
|
||||
pairData.second, &JsonRpcClientWorker::initClient, Qt::QueuedConnection);
|
||||
|
||||
QObject::connect(this, &rpc_finsTcp::writeCallSignal,
|
||||
pairData.second, &JsonRpcClientWorker::writeCallSlot, Qt::QueuedConnection);
|
||||
pairData.first->start();
|
||||
|
||||
while (pairData.second->connection == None)
|
||||
QThread::msleep(1);
|
||||
|
||||
if (pairData.second->connection == Disconnected) {
|
||||
qDebug() << "JsonRpcClientSubThread connection failed! threadId" << i;
|
||||
}
|
||||
else if (pairData.second->connection == Connected) {
|
||||
qDebug() << "JsonRpcClientSubThread connected successfully! threadId" << i;
|
||||
}
|
||||
}
|
||||
void rpc_finsTcp::initHearBeatThread() {
|
||||
hearBeatThread = new QThread();
|
||||
hearBeatClinet = new JsonRpcClientWorker(-1);
|
||||
hearBeatClinet->moveToThread(hearBeatThread);
|
||||
|
||||
QObject::connect(this, &rpc_finsTcp::initRpcClient,
|
||||
hearBeatClinet, &JsonRpcClientWorker::initClient, Qt::QueuedConnection);
|
||||
|
||||
QObject::connect(this, &rpc_finsTcp::writeCallSignal,
|
||||
hearBeatClinet, &JsonRpcClientWorker::writeCallSlot, Qt::QueuedConnection);
|
||||
hearBeatThread->start();
|
||||
while (hearBeatClinet->connection == None)
|
||||
QThread::msleep(1);
|
||||
|
||||
if (hearBeatClinet->connection == Disconnected) {
|
||||
qDebug() << "JsonRpcClientSubThread connection failed! heartBeatThread";
|
||||
}
|
||||
else if (hearBeatClinet->connection == Connected) {
|
||||
qDebug() << "JsonRpcClientSubThread connected successfully! threadId heartBeatThread";
|
||||
}
|
||||
}
|
||||
|
||||
bool rpc_finsTcp::initParas(QByteArray& data){
|
||||
startProcess("./json_rpc_server_1_1_0.exe");
|
||||
QThread::msleep(500);
|
||||
write_JsonRpcClients = std::vector<std::pair<QThread*, JsonRpcClientWorker*>>(threadCount);
|
||||
for (int i = 0; i < write_JsonRpcClients.size(); i++) {
|
||||
initClientAndThread(write_JsonRpcClients[i],i);
|
||||
}
|
||||
//心跳线程
|
||||
initHearBeatThread();
|
||||
//qDebug() << "返回结果:" << result;
|
||||
emit initRpcClient();
|
||||
emit writeCallSignal("init", QJsonArray{ m_IP,m_port }, "finstcp", -1);
|
||||
for (int i = 0; i < write_JsonRpcClients.size(); i++)
|
||||
emit writeCallSignal("init", QJsonArray{ m_IP,m_port }, "finstcp", i);
|
||||
//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 JsonRpcClient::call(const QString& method, const QJsonArray& params, const QString& module){
|
||||
QMutexLocker locker(&mutex_);
|
||||
if (socket_.state() != QAbstractSocket::ConnectedState) {
|
||||
if (!reconnect()) return QVariant();
|
||||
}
|
||||
int myId = idCounter_++;
|
||||
QJsonObject req{
|
||||
{"jsonrpc", "2.0"},
|
||||
{"method", method},
|
||||
{"params", params},
|
||||
{"id", myId}
|
||||
};
|
||||
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) {
|
||||
auto commands = params.split("_");
|
||||
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();
|
||||
}
|
||||
|
||||
QJsonObject respObj;
|
||||
if (!waitAndReadResponse(myId, respObj)) {
|
||||
qWarning() << "[JsonRpcClient] Read timeout or parse error.";
|
||||
return QByteArray();
|
||||
}
|
||||
QString b64 = respObj.value("result").toString();
|
||||
QByteArray decoded = QByteArray::fromBase64(b64.toUtf8());
|
||||
if (b64.contains("error") || decoded.size()% commands[3].toInt() != 0) {
|
||||
qWarning() << "[ERROR]" << b64;
|
||||
QThread::msleep(500);
|
||||
return 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);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
#ifndef rpc_finsTcp_H
|
||||
#define rpc_finsTcp_H
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QByteArray>
|
||||
#include <iostream>
|
||||
#include <QQueue>
|
||||
#include <QDebug>
|
||||
#include <subModuleBase.h>
|
||||
#include <QMutex>
|
||||
|
||||
#include <QObject>
|
||||
#include <QTcpSocket>
|
||||
#include <QTimer>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonDocument>
|
||||
#include <QHostAddress>
|
||||
#include <qmap.h>
|
||||
#include <qthread.h>
|
||||
enum connectionStatus {
|
||||
None,
|
||||
Disconnected,
|
||||
Connected
|
||||
};
|
||||
class JsonRpcClient : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
connectionStatus _connectionStatus = None;
|
||||
JsonRpcClient(const QString& host = "127.0.0.1", quint16 port = 9000);
|
||||
void writeCall(const QString& method, const QJsonArray& params = {}, const QString& module = QString());
|
||||
QVariant call(const QString& method, const QJsonArray& params = {}, const QString& module = QString());
|
||||
QByteArray finsReadCall(const QString& method, const QString& params = "", const QString& module = QString());
|
||||
bool reconnect(); // 主动重连,或 call() 失败时调用
|
||||
private:
|
||||
// 解析累计缓冲中的完整 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
|
||||
public:
|
||||
connectionStatus connection;
|
||||
QQueue<QByteArray> readDataQueue;
|
||||
JsonRpcClientWorker(const int& threadIdIn):threadId(threadIdIn){
|
||||
|
||||
}
|
||||
public slots:
|
||||
void initClient() {
|
||||
_JsonRpcClient = new JsonRpcClient();
|
||||
connection = _JsonRpcClient->_connectionStatus;
|
||||
}
|
||||
void writeCallSlot(const QString& method, const QJsonArray& params, const QString& module = QString(),const int& threadIndex = -1) {
|
||||
if (_JsonRpcClient && threadId == threadIndex) {
|
||||
if (threadId != -1)qDebug() << params << threadId;
|
||||
_JsonRpcClient->call(method, params, module);
|
||||
}
|
||||
}
|
||||
private:
|
||||
int threadId = 0;
|
||||
JsonRpcClient* _JsonRpcClient = nullptr;
|
||||
};
|
||||
class rpc_finsTcp :public rpcModuleBase
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
rpc_finsTcp();
|
||||
virtual ~rpc_finsTcp();
|
||||
bool readData(std::vector<cv::Mat>&, QByteArray&);// readData将PLC读取或者发送的返回值发回给主线程,通过全局变量的方式逐条发送
|
||||
bool writeData(std::vector<cv::Mat>&, QByteArray&);// writeData调用PLC的收发,将需要的数据发给寄存器,返回OK/NG
|
||||
bool initParas(QByteArray&);
|
||||
bool run();
|
||||
signals:
|
||||
void initRpcClient();
|
||||
void writeCallSignal(const QString& method, const QJsonArray& params, const QString& module,const int& threadId);
|
||||
private:
|
||||
void initHearBeatThread();
|
||||
void initClientAndThread(std::pair<QThread*, JsonRpcClientWorker*>&, const int& i);
|
||||
QMutex mutex;
|
||||
QMap<QString,JsonRpcClient*> read_JsonRpcClient; // 存储多个 JsonRpcClient 实例
|
||||
std::vector<std::pair<QThread* ,JsonRpcClientWorker*>> write_JsonRpcClients;
|
||||
|
||||
JsonRpcClientWorker* hearBeatClinet;
|
||||
QThread* hearBeatThread;
|
||||
|
||||
QString m_IP;
|
||||
int m_port,threadCount = 1;
|
||||
QQueue<QByteArray> readDataQueue;
|
||||
QMutex threadUseIndexMutex;
|
||||
int threadUseIndex = 0;
|
||||
};
|
||||
#pragma once
|
||||
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Q_DECL_EXPORT rpc_finsTcp * create();
|
||||
Q_DECL_EXPORT void destory(rpc_finsTcp * ptr);
|
||||
}
|
||||
|
||||
#endif // rpc_finsTcp_H
|
||||
@@ -0,0 +1,71 @@
|
||||
# 获取获取当前目录名
|
||||
get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
|
||||
set(DLL_NAMES "basler" "opencv")
|
||||
foreach(child ${DLL_NAMES})
|
||||
LIST(APPEND ENV_INCLUDE ${${child}_include})
|
||||
LIST(APPEND ENV_LIB ${${child}_lib})
|
||||
LIST(APPEND ENV_TARGET ${${child}_target_link})
|
||||
endforeach()
|
||||
message(" ENV_INCLUDE : " ${ENV_INCLUDE} )
|
||||
message(" ENV_LIB : " ${ENV_LIB} )
|
||||
message(" ENV_TARGET : " ${ENV_TARGET} )
|
||||
include_directories(
|
||||
|
||||
${ENV_INCLUDE}
|
||||
)
|
||||
|
||||
link_directories (
|
||||
${ENV_LIB}
|
||||
|
||||
)
|
||||
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
SET(CMAKE_CXX_STANDARD 11)
|
||||
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
SET(CMAKE_AUTOUIC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
FILE(GLOB HEAD_FILES "./*.h" )
|
||||
FILE(GLOB SRC_FILES "./*.cpp")
|
||||
FILE(GLOB UI_FILES "./*.ui")
|
||||
|
||||
|
||||
#find_package(Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Network REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Network REQUIRED)
|
||||
|
||||
add_library(${CURRENT_FOLDER} SHARED
|
||||
${HEAD_FILES}
|
||||
${SRC_FILES}
|
||||
${UI_FILES}
|
||||
)
|
||||
|
||||
|
||||
|
||||
set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}
|
||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
|
||||
)
|
||||
|
||||
|
||||
target_link_libraries(${CURRENT_FOLDER} PRIVATE
|
||||
${ENV_TARGET}
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt5::Network
|
||||
)
|
||||
|
||||
|
||||
# target_compile_definitions(${CURRENT_FOLDER} PRIVATE HD_AIDEMO_MODULE_LIBRARY)
|
||||
|
||||
|
||||
|
||||
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model end : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
Binary file not shown.
@@ -51,6 +51,7 @@ rpc_finsTcp::~rpc_finsTcp() {
|
||||
// 断开所有信号槽连接
|
||||
subThread->disconnect();
|
||||
|
||||
// 如果线程在运行,优雅退出
|
||||
if (subThread->isRunning()) {
|
||||
subThread->quit();
|
||||
// 最多等待3秒,防止死锁
|
||||
@@ -62,6 +62,7 @@ public slots:
|
||||
void writeCallSlot(const QString& method, const QJsonArray& params, const QString& module = QString()) {
|
||||
if (_JsonRpcClient) {
|
||||
//qDebug() << params;
|
||||
//qDebug() << method;
|
||||
_JsonRpcClient->call(method, params, module);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user