优化相机模块,优化rpc模块
This commit is contained in:
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"xutility": "cpp"
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -2,20 +2,7 @@
|
||||
#include <filesystem>
|
||||
#include <struct.h>
|
||||
//#include <appconfigStruct.h>
|
||||
typedef dsModuleBase* (*CreateFunction)();
|
||||
typedef void (*ReleaseFunction)(dsModuleBase* animal);
|
||||
|
||||
typedef struct {
|
||||
QString m_stationKy;
|
||||
QString key; // 相机名称
|
||||
QString dllPath; // 模块名称
|
||||
QString task_thread_index = "-1";// 存储当前算法属于那个任务线程
|
||||
QByteArray m_initByte; // 传递初始化参数
|
||||
dsModuleBase* module_ptr = nullptr; // 存储模块指针
|
||||
ReleaseFunction destory_ptr; // 释放
|
||||
cameraStruct _cameraStruct;//外部传入数据
|
||||
bool init = false;
|
||||
}cameraModule;
|
||||
|
||||
static void createDirectoryIfNotExists(const std::string& path) {
|
||||
// 检查路径是否存在
|
||||
|
||||
@@ -28,12 +28,11 @@ static MV_CC_DEVICE_INFO_LIST searchMvDevice()
|
||||
return m_stDevList;
|
||||
}
|
||||
|
||||
camera::camera(cameraModule cameraModulePtrIn, int indexIn, qtFuncBridge* bridgeIn)
|
||||
camera::camera(cameraStruct configIn, int indexIn, qtFuncBridge* bridgeIn)
|
||||
{
|
||||
bridge = bridgeIn;
|
||||
cameraModulePtr = cameraModulePtrIn;
|
||||
config = cameraModulePtr._cameraStruct;
|
||||
cameraName = cameraModulePtr.key;
|
||||
config = configIn;
|
||||
cameraName = QString::fromStdString(config.key);
|
||||
index = indexIn;
|
||||
lastUpdateTime.start();
|
||||
this->start();
|
||||
@@ -64,21 +63,21 @@ void camera::run()
|
||||
// QPixmap pixmap;
|
||||
// cvMatToQPixMap(data->oriImgs[i], pixmap);
|
||||
// showImgPack* pack = new showImgPack(
|
||||
// cameraModulePtr._cameraStruct.imageShowList[imgShowCnt].first,
|
||||
// cameraModulePtr._cameraStruct.imageShowList[imgShowCnt].second
|
||||
// config._cameraStruct.imageShowList[imgShowCnt].first,
|
||||
// config._cameraStruct.imageShowList[imgShowCnt].second
|
||||
// );
|
||||
// pack->img = pixmap;
|
||||
// emit bridge->displayWidget_sendImg(pack);
|
||||
|
||||
// imgShowCnt++;
|
||||
// if (imgShowCnt >= cameraModulePtr._cameraStruct.imageShowList.size())
|
||||
// if (imgShowCnt >= config._cameraStruct.imageShowList.size())
|
||||
// imgShowCnt = 0;
|
||||
// }
|
||||
|
||||
//}
|
||||
//else {
|
||||
// showLost++;
|
||||
// qDebug() << cameraModulePtr.dllPath << "Lost show";
|
||||
// qDebug() << config.dllPath << "Lost show";
|
||||
//}
|
||||
break;
|
||||
}
|
||||
@@ -89,22 +88,19 @@ void camera::run()
|
||||
QThread::msleep(10);
|
||||
}
|
||||
}
|
||||
|
||||
cameraManager::~cameraManager()
|
||||
{
|
||||
for (auto camera : cameras) {
|
||||
delete camera.second;
|
||||
}
|
||||
for (auto module : camerasVec) {
|
||||
for (auto& module : _cameraStructs) {
|
||||
dsModuleBase* base_ptr = module.module_ptr;
|
||||
delete base_ptr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void cameraManager::run()
|
||||
{
|
||||
void cameraManager::run(){
|
||||
if (initFlag == true)
|
||||
return;
|
||||
#pragma region 加载相机dll
|
||||
@@ -127,25 +123,23 @@ void cameraManager::run()
|
||||
MV_CC_DEVICE_INFO_LIST m_stDevList = searchMvDevice();
|
||||
QByteArray mvDevices = MV_CC_DeviceInfoListToQByteArray(m_stDevList);
|
||||
|
||||
for (auto i = 0; i < camerasVec.size(); i++) {
|
||||
cameraModule& m_module = camerasVec[i];
|
||||
QString dllPath = m_module.dllPath;
|
||||
QString key = m_module.key;
|
||||
for (auto i = 0; i < _cameraStructs.size(); i++) {
|
||||
auto& m_module = _cameraStructs[i];
|
||||
QString dllPath = QString::fromStdString(m_module.dllPath);
|
||||
QString key = QString::fromStdString(m_module.key);
|
||||
//传递初始化参数
|
||||
QByteArray initByte = m_module.m_initByte;
|
||||
QByteArray m_keyByte = key.toUtf8();
|
||||
//遍历是否有相同key的相机,如果有直接复制指针
|
||||
for (int count = 0; count < camerasVec.size(); count++)
|
||||
if (!camerasVec[count].key.compare(m_module.key) && count < i)
|
||||
m_module.module_ptr = camerasVec[count].module_ptr;
|
||||
for (int count = 0; count < _cameraStructs.size(); count++)
|
||||
if (!_cameraStructs[count].key.compare(m_module.key) && count < i)
|
||||
m_module.module_ptr = _cameraStructs[count].module_ptr;
|
||||
m_module.module_ptr->writeData(vec_mat, m_keyByte); //初始化相机
|
||||
//非海康相机可跳过
|
||||
for (int i = 0; i < m_stDevList.nDeviceNum; i++)
|
||||
{
|
||||
for (int i = 0; i < m_stDevList.nDeviceNum; i++){
|
||||
std::string userDefineName = static_cast<std::string>((LPCSTR)m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chUserDefinedName);
|
||||
std::string serialNumber = static_cast<std::string>((LPCSTR)m_stDevList.pDeviceInfo[i]->SpecialInfo.stGigEInfo.chSerialNumber);
|
||||
if (!serialNumber.compare(m_module.key.toStdString()) || !userDefineName.compare(m_module.key.toStdString()))
|
||||
{
|
||||
if (!serialNumber.compare(m_module.key) || !userDefineName.compare(m_module.key)){
|
||||
m_module.module_ptr->writeData(vec_mat, mvDevices);
|
||||
break;
|
||||
}
|
||||
@@ -155,42 +149,35 @@ void cameraManager::run()
|
||||
}
|
||||
status = NotInit;
|
||||
bool initReuslt = true;
|
||||
for (auto i = 0; i < camerasVec.size(); i++)
|
||||
{
|
||||
cameraModule m_module = camerasVec.at(i);
|
||||
if (m_module.init == true)
|
||||
for (auto i = 0; i < _cameraStructs.size(); i++){
|
||||
auto& cameraStruct = _cameraStructs[i];
|
||||
if (cameraStruct.init == true)
|
||||
continue;
|
||||
QByteArray initByte = m_module.m_initByte;
|
||||
if (m_module.module_ptr->initParas(initByte))
|
||||
{
|
||||
camera* _camera = new camera(m_module, cameras.size(), bridge);
|
||||
cameras.insert(std::make_pair(m_module.key.toStdString(), _camera));
|
||||
emit bridge->loadingWindow_appendLog("相机" + m_module.key + "初始化成功", "green");
|
||||
QByteArray initByte = cameraStruct.m_initByte;
|
||||
if (cameraStruct.module_ptr->initParas(initByte)){
|
||||
camera* _camera = new camera(cameraStruct, cameras.size(), bridge);
|
||||
cameras.insert(std::make_pair(cameraStruct.key, _camera));
|
||||
emit bridge->loadingWindow_appendLog("相机" + QString::fromStdString(cameraStruct.key) + "初始化成功", "green");
|
||||
qDebug() << "[INFO] " << " initParas success!";
|
||||
m_module.init = true;
|
||||
cameraStruct.init = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
else{
|
||||
QByteArray errorStr("getStatus");
|
||||
m_module.module_ptr->readData(vec_mat, errorStr);
|
||||
cameraStruct.module_ptr->readData(vec_mat, errorStr);
|
||||
initReuslt = false;
|
||||
qCritical() << "[Error] " << " moduleName:" << m_module.dllPath << " initParas failed!";
|
||||
emit bridge->loadingWindow_appendLog("相机" + m_module.key + "初始化失败->" + errorStr, "red");
|
||||
qCritical() << "[Error] " << " moduleName:" << QString::fromStdString(cameraStruct.dllPath) << " initParas failed!";
|
||||
emit bridge->loadingWindow_appendLog("相机" + QString::fromStdString(cameraStruct.key) + "初始化失败->" + errorStr, "red");
|
||||
}
|
||||
}
|
||||
if (initReuslt == true)
|
||||
{
|
||||
if (initReuslt == true){
|
||||
initFlag = true;
|
||||
status = InitOK;
|
||||
}
|
||||
else
|
||||
status = InitFailure;
|
||||
}
|
||||
bool cameraManager::loadModule(cameraStruct _cameraStruct)
|
||||
{
|
||||
QString task_thread_index = 0;
|
||||
try
|
||||
{
|
||||
bool cameraManager::loadModule(cameraStruct& _cameraStruct){
|
||||
try{
|
||||
QString keyName = QString::fromStdString(_cameraStruct.key);
|
||||
QString dllPath = QString::fromStdString(_cameraStruct.dllPath);// 相机模块名
|
||||
QString module_path = "./" + dllPath;
|
||||
@@ -213,8 +200,7 @@ bool cameraManager::loadModule(cameraStruct _cameraStruct)
|
||||
QLibrary* m_lib = new QLibrary(module_path);
|
||||
lib_list.append(m_lib);
|
||||
bool flag = m_lib->load();
|
||||
if (!m_lib->isLoaded())
|
||||
{
|
||||
if (!m_lib->isLoaded()){
|
||||
|
||||
qDebug() << "[Error] " << " Loaded error:" << m_lib->errorString();
|
||||
bridge->loadingWindow_appendLog("加载相机模块" + dllPath + "失败->" + m_lib->errorString(), "red");
|
||||
@@ -223,29 +209,18 @@ bool cameraManager::loadModule(cameraStruct _cameraStruct)
|
||||
|
||||
CreateFunction createFun = (CreateFunction)m_lib->resolve("create");
|
||||
ReleaseFunction releaseFun = (ReleaseFunction)m_lib->resolve("destory");
|
||||
if (createFun && releaseFun)
|
||||
{
|
||||
cameraModule m_module;
|
||||
m_module.key = keyName;
|
||||
m_module.m_initByte = QByteArray::fromStdString( _cameraStruct.connectionName);
|
||||
m_module.dllPath = dllPath;
|
||||
m_module.module_ptr = createFun();
|
||||
m_module.destory_ptr = releaseFun;
|
||||
m_module._cameraStruct = _cameraStruct;
|
||||
if (!task_thread_index.isEmpty())
|
||||
m_module.task_thread_index = task_thread_index;
|
||||
|
||||
camerasVec.push_back(m_module);
|
||||
if (createFun && releaseFun){
|
||||
_cameraStruct.module_ptr = createFun();
|
||||
_cameraStruct.destory_ptr = releaseFun;
|
||||
_cameraStruct.m_initByte = QByteArray::fromStdString(_cameraStruct.connectionName);
|
||||
}
|
||||
else
|
||||
{
|
||||
else{
|
||||
delete m_lib;
|
||||
m_lib = nullptr;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (QString event)
|
||||
{
|
||||
catch (QString event){
|
||||
qCritical() << "[Error] " << " event:" << event;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -11,57 +11,66 @@
|
||||
#include <future>
|
||||
#include <qtBridge.h>
|
||||
#include <detData.h>
|
||||
typedef dsModuleBase* (*CreateFunction)();
|
||||
typedef void (*ReleaseFunction)(dsModuleBase* animal);
|
||||
|
||||
struct cameraStruct {
|
||||
int index;
|
||||
std::string key;
|
||||
std::string connectionName;//per Sec
|
||||
std::string serialNum;
|
||||
std::string dllPath;
|
||||
std::vector <std::string> oriSaveFormat;
|
||||
std::vector<std::pair<QString, QString>>imageShowList;
|
||||
|
||||
QByteArray m_initByte; // 传递初始化参数
|
||||
dsModuleBase* module_ptr = nullptr; // 存储模块指针
|
||||
ReleaseFunction destory_ptr; // 释放
|
||||
bool init = false;
|
||||
};
|
||||
|
||||
//硬触发要求在触发相机前给出触发信号
|
||||
class backEndManager;
|
||||
class camera : public QThread
|
||||
{
|
||||
class camera : public QThread{
|
||||
Q_OBJECT
|
||||
public:
|
||||
QTime lastUpdateTime;
|
||||
QString cameraName;
|
||||
int imgShowCnt = 0;
|
||||
cameraModule cameraModulePtr;
|
||||
cameraStruct config;
|
||||
camera(cameraModule cameraModulePtrIn, int indexIn, qtFuncBridge* bridgeIn);
|
||||
~camera()
|
||||
{
|
||||
camera(cameraStruct configIn, int indexIn, qtFuncBridge* bridgeIn);
|
||||
~camera(){
|
||||
runFlag = false;
|
||||
this->terminate();
|
||||
while (this->isRunning() == true);
|
||||
}
|
||||
void run();
|
||||
void stop()
|
||||
{
|
||||
void stop(){
|
||||
runFlag = false;
|
||||
while (this->isRunning() == true);
|
||||
}
|
||||
void getImgQueueSize();
|
||||
void captureImage(std::shared_ptr <detData> dataIn)
|
||||
{
|
||||
void captureImage(std::shared_ptr <detData> dataIn){
|
||||
QMutexLocker locker(&mutex);
|
||||
requestQueue.enqueue(dataIn);
|
||||
//std::thread([this]() {trigger();}).detach();
|
||||
}
|
||||
|
||||
//相机操作
|
||||
bool trigger()
|
||||
{
|
||||
if (!cameraModulePtr.module_ptr->run())
|
||||
{
|
||||
bool trigger(){
|
||||
if (!config.module_ptr->run()){
|
||||
qCritical() << "[Error] " << " m_name:" << cameraName << " run failed!";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
double getCameraValue()//点激光相机专用
|
||||
{
|
||||
double getCameraValue(){//点激光相机专用
|
||||
double value = 0;
|
||||
std::vector<cv::Mat> camera_mat;
|
||||
QByteArray task_name;
|
||||
|
||||
int cnt = 0;
|
||||
while (!cameraModulePtr.module_ptr->readData(camera_mat, task_name))
|
||||
{
|
||||
while (!config.module_ptr->readData(camera_mat, task_name)){
|
||||
QThread::msleep(10);
|
||||
cnt++;
|
||||
if (cnt > 500)
|
||||
@@ -70,10 +79,9 @@ public:
|
||||
value = task_name.toDouble();
|
||||
return value;
|
||||
}
|
||||
void getCameraImg(std::vector<cv::Mat>& mats,int imgAmountMin)
|
||||
{
|
||||
void getCameraImg(std::vector<cv::Mat>& mats,int imgAmountMin){
|
||||
QByteArray task_name;
|
||||
if (!cameraModulePtr.module_ptr->readData(mats, task_name)) {
|
||||
if (!config.module_ptr->readData(mats, task_name)) {
|
||||
if (mats.size() == 0) {
|
||||
qDebug() << "camera_mat size 0,insert blank image";
|
||||
mats = std::vector<cv::Mat>(imgAmountMin, cv::Mat::zeros(100, 100, CV_8UC3));
|
||||
@@ -81,16 +89,13 @@ public:
|
||||
}
|
||||
qDebug() << __FUNCTION__ << " line:" << __LINE__ << "camera_mat size:" << mats.size();
|
||||
}
|
||||
void setDigitalShift(float value)
|
||||
{
|
||||
void setDigitalShift(float value){
|
||||
readData("DigitalShift_" + std::to_string(value));
|
||||
}
|
||||
void setExposureTime(float value)
|
||||
{
|
||||
void setExposureTime(float value){
|
||||
readData("exposure_" + std::to_string(value));
|
||||
}
|
||||
void setUserSet(int value)
|
||||
{
|
||||
void setUserSet(int value){
|
||||
readData("userset_" + std::to_string(value));
|
||||
}
|
||||
private:
|
||||
@@ -99,7 +104,7 @@ private:
|
||||
{
|
||||
QByteArray task_name(QByteArray::fromStdString(str));
|
||||
std::vector<cv::Mat> camera_mat;
|
||||
if (!cameraModulePtr.module_ptr->readData(camera_mat, task_name))
|
||||
if (!config.module_ptr->readData(camera_mat, task_name))
|
||||
qCritical() << "[Error] " << "set exposure error!";
|
||||
}
|
||||
int index = 0;
|
||||
@@ -111,26 +116,22 @@ private:
|
||||
int imgLost = 0;//未取用从而丢失的图片数量
|
||||
int showLost = 0;//因为窗口刷新速率低而未显示的数量
|
||||
};
|
||||
class cameraManager : public serviceModule
|
||||
{
|
||||
class cameraManager : public serviceModule{
|
||||
Q_OBJECT
|
||||
public:
|
||||
cameraManager(nlohmann::ordered_json& json, qtFuncBridge* bridgeIn) {
|
||||
bridge = bridgeIn;
|
||||
auto cameraJson = json["CameraSetting"];
|
||||
for (auto data : cameraJson)
|
||||
{
|
||||
for (auto data : cameraJson){
|
||||
cameraStruct _cameraStruct;
|
||||
_cameraStruct.key = data["key"];
|
||||
_cameraStruct.connectionName = data["connectionName"];
|
||||
_cameraStruct.dllPath = data["dllPath"];
|
||||
_cameraStruct.oriSaveFormat = data["oriSaveFormat"];
|
||||
for (auto& imageShow : data["imageShow"])
|
||||
{
|
||||
for (auto& imageShow : data["imageShow"]){
|
||||
QString str = QString::fromStdString(imageShow);
|
||||
QStringList l = str.split("#");
|
||||
if (l.size() < 2)
|
||||
{
|
||||
if (l.size() < 2){
|
||||
qDebug() << "Imagehsow 格式错误,例:窗口名#类型名";
|
||||
std::cout << "Imagehsow 格式错误,例:窗口名#类型名" <<std::endl;
|
||||
continue;
|
||||
@@ -140,20 +141,16 @@ public:
|
||||
_cameraStructs.push_back(_cameraStruct);
|
||||
}
|
||||
}
|
||||
|
||||
~cameraManager();
|
||||
|
||||
void run();
|
||||
std::unordered_map<std::string, camera*>cameras;//key 相机名
|
||||
camera* getCamera(std::string cameraName)
|
||||
{
|
||||
camera* getCamera(std::string cameraName){
|
||||
auto camera = cameras.find(cameraName);
|
||||
if (camera != cameras.end())
|
||||
return camera->second;
|
||||
return nullptr;
|
||||
}
|
||||
void stop()
|
||||
{
|
||||
void stop(){
|
||||
for (auto camera : cameras)
|
||||
camera.second->stop();
|
||||
}
|
||||
@@ -162,17 +159,14 @@ private:
|
||||
std::vector<cameraStruct> _cameraStructs;//相机配置结构体
|
||||
qtFuncBridge* bridge;
|
||||
|
||||
bool loadModule(cameraStruct _cameraStruct);
|
||||
std::vector<cameraModule>camerasVec;//用于初始化和销毁
|
||||
bool loadModule(cameraStruct& _cameraStruct);
|
||||
std::vector<cv::Mat> vec_mat;//没啥用,一直保持为空就好
|
||||
QList<QLibrary*> lib_list;
|
||||
std::map<QString,bool> m_usedDllPath;
|
||||
public slots:
|
||||
void cameraTrigger(std::string Name)
|
||||
{
|
||||
void cameraTrigger(std::string Name){
|
||||
auto camera=cameras.find(Name);
|
||||
if (camera != cameras.end())
|
||||
{
|
||||
if (camera != cameras.end()){
|
||||
camera->second->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
+10
-8
@@ -82,20 +82,16 @@ public:
|
||||
};
|
||||
class detDataManager{
|
||||
public:
|
||||
detDataManager(triggerManager* in_triggerManager)
|
||||
:_triggerManager(in_triggerManager){
|
||||
|
||||
}
|
||||
std::unordered_map<QString, std::shared_ptr<detData>>map;
|
||||
QMutex dataMutex;
|
||||
detDataManager(){
|
||||
|
||||
}
|
||||
std::shared_ptr <detData> createDetData(QString IN_cameraKeyName,std::string IN_SN, int imgAmountMin,std::vector<std::string> oriFormat) {
|
||||
QMutexLocker locker(&dataMutex);
|
||||
std::shared_ptr <detData>dataPtr(new detData());
|
||||
dataPtr->cameraKeyName = IN_cameraKeyName.toStdString();
|
||||
dataPtr->imgSaveNameParameter.push_back(IN_cameraKeyName.toStdString());
|
||||
dataPtr->oriFormat = oriFormat;
|
||||
dataPtr->triggerPtr = _triggerManager;
|
||||
dataPtr->triggerPtr;
|
||||
dataPtr->SNcode = IN_SN;
|
||||
dataPtr->imgAmountMin = imgAmountMin;
|
||||
dataPtr->dManager = this;
|
||||
@@ -131,7 +127,13 @@ public:
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void setTriggerManager(triggerManager* _triggerManagerIN) {
|
||||
QMutexLocker locker(&dataMutex);
|
||||
_triggerManager = _triggerManagerIN;
|
||||
}
|
||||
private:
|
||||
triggerManager* _triggerManager;
|
||||
triggerManager* _triggerManager = nullptr;
|
||||
QMutex dataMutex;
|
||||
std::unordered_map<QString, std::shared_ptr<detData>>map;
|
||||
};
|
||||
#pragma once
|
||||
@@ -11,8 +11,6 @@ triggerManager::triggerManager(detProcess* _detProcessIn, qtFuncBridge* bridgeIn
|
||||
_detProcess = _detProcessIn;
|
||||
dManager = _detProcessIn->_serviceManager._detDataManager;
|
||||
_cameraManager = _detProcessIn->_serviceManager._cameraManager;
|
||||
//_threadManager = &_detProcessIn->_threadManager;
|
||||
//_lightSourceManager = &_detProcessIn->_lightSourceManager;
|
||||
for (auto& d : triggerJson["readAllCmd"]) {
|
||||
readAllStruct _struct;
|
||||
_struct.readAllCmd = QByteArray::fromStdString(d);
|
||||
@@ -135,9 +133,24 @@ void triggerManager::decodeCameraCMD(readAllStruct& _struct, QByteArray byte)
|
||||
if (isConnected == true) {
|
||||
lostConnectionCountTimer.start();
|
||||
std::cout<< "与PLC的连接已断开,正在尝试重连" << std::endl;
|
||||
std::cout << "错误类型:读取到的数据为空" << std::endl;
|
||||
}
|
||||
if (lostConnectionRePrintTimer.elapsed() > 1000) {
|
||||
qCritical() << "ERROR:cant read data from Fins,无法从fins读取数据";
|
||||
qCritical() << "ERROR:cant read data from Fins data size=0,无法从fins读取数据 数据为空";
|
||||
emit bridge->setPlcConnectionError();
|
||||
isConnected = false;
|
||||
lostConnectionRePrintTimer.start();
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (byte.size() != _struct.readLength * 2 && byte.size() != _struct.readLength) {
|
||||
if (isConnected == true) {
|
||||
lostConnectionCountTimer.start();
|
||||
std::cout << "与PLC的连接已断开,正在尝试重连" << std::endl;
|
||||
std::cout << "错误类型:读取到的数据大小不匹配" << std::endl;
|
||||
}
|
||||
if (lostConnectionRePrintTimer.elapsed() > 1000) {
|
||||
qCritical() << "ERROR:cant read data from Fins data size<preset,无法从fins读取数据 数据大小不匹配";
|
||||
emit bridge->setPlcConnectionError();
|
||||
isConnected = false;
|
||||
lostConnectionRePrintTimer.start();
|
||||
|
||||
+63
-22
@@ -16,19 +16,55 @@ public:
|
||||
db(dbIn),bridge(bridgeIn),json(jsonIn){
|
||||
|
||||
}
|
||||
|
||||
// 对普通指针的安全删除
|
||||
template<typename T>
|
||||
void safeDelete(T*& ptr) {
|
||||
if (ptr) { delete ptr; ptr = nullptr; }
|
||||
}
|
||||
|
||||
// 尝试对基于 QThread 的 serviceModule 进行关停,然后删除
|
||||
void safeShutdownDelete(serviceModule* ptr) {
|
||||
if (!ptr) return;
|
||||
// 如果对象正在运行,尝试停止
|
||||
if (ptr->isRunning()) {
|
||||
// 如果存在 stop 槽,则尝试调用
|
||||
QMetaObject::invokeMethod(ptr, "stop", Qt::DirectConnection);
|
||||
// 作为后备,尝试退出事件循环
|
||||
QMetaObject::invokeMethod(ptr, "quit", Qt::DirectConnection);
|
||||
// 等待其退出,给予一定时间
|
||||
if (!ptr->wait(2000)) {
|
||||
// 仍在运行时,作为最后手段强制终止
|
||||
ptr->terminate();
|
||||
ptr->wait(1000);
|
||||
}
|
||||
}
|
||||
delete ptr; ptr = nullptr;
|
||||
}
|
||||
|
||||
void init() {
|
||||
_serviceManager._imgSaveThreadManager = new imgSaveThreadManager(json["imgSaveBasePath"]);
|
||||
_serviceManager._cameraManager = new cameraManager(json, bridge);
|
||||
_serviceManager._triggerManager = new triggerManager(this, bridge, json["Triggers"]);
|
||||
_serviceManager._detDataManager = new detDataManager(_serviceManager._triggerManager);
|
||||
// 创建/重建需要的服务模块,避免重复创建
|
||||
if (!_serviceManager._imgSaveThreadManager) {
|
||||
_serviceManager._imgSaveThreadManager = new imgSaveThreadManager(json["imgSaveBasePath"]);
|
||||
}
|
||||
if (!_serviceManager._cameraManager) {
|
||||
_serviceManager._cameraManager = new cameraManager(json, bridge);
|
||||
}
|
||||
if (!_serviceManager._triggerManager) {
|
||||
_serviceManager._triggerManager = new triggerManager(this, bridge, json["Triggers"]);
|
||||
}
|
||||
if (initOnce == false) {
|
||||
initOnce = true;
|
||||
_csvWriter = new CsvWriter(db);
|
||||
_serviceManager._detDataManager = new detDataManager();
|
||||
_missonResultHandle = new missonResultHandle(bridge);
|
||||
_serviceManager._missonResultHandle = _missonResultHandle;
|
||||
_serviceManager.dataBase = db;
|
||||
_serviceManager._csvWriter = _csvWriter;
|
||||
_serviceManager._handleAiModelManager = new handleAiModelManager(json, bridge);
|
||||
// handleAiModelManager 与 CLI 等只在首次初始化创建
|
||||
if (!_serviceManager._handleAiModelManager) {
|
||||
_serviceManager._handleAiModelManager = new handleAiModelManager(json, bridge);
|
||||
}
|
||||
connect(bridge, &qtFuncBridge::reInitConfig, this, [=]() {reinitConfig(); });
|
||||
_cliManager = new CLIManager(&_serviceManager, bridge);
|
||||
}
|
||||
@@ -52,15 +88,29 @@ public:
|
||||
|
||||
// 重新初始化配置
|
||||
void reinitConfig() {
|
||||
// 1. 释放已有资源
|
||||
if (_serviceManager._imgSaveThreadManager) { delete _serviceManager._imgSaveThreadManager; _serviceManager._imgSaveThreadManager = nullptr; }
|
||||
if (_serviceManager._cameraManager) { delete _serviceManager._cameraManager; _serviceManager._cameraManager = nullptr; }
|
||||
if (_serviceManager._triggerManager) { delete _serviceManager._triggerManager; _serviceManager._triggerManager = nullptr; }
|
||||
//if (_serviceManager._threadManager) { delete _serviceManager._threadManager; _serviceManager._threadManager = nullptr; }
|
||||
if (_serviceManager._detDataManager) { delete _serviceManager._detDataManager; _serviceManager._detDataManager = nullptr; }
|
||||
// 1. 优雅停止并释放已有运行中的服务模块
|
||||
// 停止并删除线程型模块
|
||||
safeShutdownDelete(_serviceManager._cameraManager);
|
||||
safeShutdownDelete(_serviceManager._triggerManager);
|
||||
// imgSaveThreadManager 可能不是 QThread,直接删除
|
||||
safeDelete(_serviceManager._imgSaveThreadManager);
|
||||
// handleAiModelManager 可能运行在后台,优雅停止后删除
|
||||
if (_serviceManager._handleAiModelManager) {
|
||||
// try invoking stop if exists
|
||||
QMetaObject::invokeMethod(_serviceManager._handleAiModelManager, "stop", Qt::DirectConnection);
|
||||
safeDelete(_serviceManager._handleAiModelManager);
|
||||
}
|
||||
|
||||
// 2. 重新初始化
|
||||
init();
|
||||
this->start();
|
||||
|
||||
// 3. 如果 detProcess 尚未运行,则启动主线程;如果已在运行,run() 应自行管理子模块的重启
|
||||
if (!this->isRunning()) {
|
||||
this->start();
|
||||
} else {
|
||||
// 已在运行的话,可以发出信号或回调,通知 run 中重载配置(这里仅 log)
|
||||
qDebug() << "detProcess already running, init refreshed. run() should handle reloading if needed.";
|
||||
}
|
||||
}
|
||||
// 初始化并运行主流程
|
||||
void run() {
|
||||
@@ -81,16 +131,7 @@ public:
|
||||
json["missionSettings"], bridge
|
||||
);
|
||||
_cliManager->initBasicPreset();
|
||||
//_threadManager->registerResultHandleCallback(
|
||||
// [this](std::shared_ptr<detData> data) {
|
||||
// detectionResultHandle(data);
|
||||
// });
|
||||
|
||||
//_threadManager->registerProcessAlgoCallback(
|
||||
// [this](std::shared_ptr<detData> data, handleAiModelManager* _handleAiModelManager) {
|
||||
// return _missionLoader._misson->processAlgo(data, _handleAiModelManager);
|
||||
// });
|
||||
|
||||
_serviceManager._detDataManager->setTriggerManager(_serviceManager._triggerManager);
|
||||
emit bridge->initResult(InitOK);
|
||||
}
|
||||
else {
|
||||
|
||||
+1
-9
@@ -5,6 +5,7 @@
|
||||
#include <simpleTools/stringAlgo.h>
|
||||
#include <simpleTools/fileManager.h>
|
||||
#include <qmutex.h>
|
||||
#include <subModuleBase.h>
|
||||
struct productSignStruct
|
||||
{
|
||||
cv::Rect posRect;
|
||||
@@ -209,15 +210,6 @@ struct triggerStruct
|
||||
std::string writeType;
|
||||
int startPos;
|
||||
};
|
||||
struct cameraStruct{
|
||||
int index;
|
||||
std::string key;
|
||||
std::string connectionName;//per Sec
|
||||
std::string serialNum;
|
||||
std::string dllPath;
|
||||
std::vector <std::string> oriSaveFormat;
|
||||
std::vector<std::pair<QString,QString>>imageShowList;
|
||||
};
|
||||
|
||||
struct sqlConfigStruct
|
||||
{
|
||||
|
||||
@@ -19,7 +19,7 @@ void appConfig::parsingSettingJson()
|
||||
softwareTile = settingJson["softwareTile"];
|
||||
imgSavePath = settingJson["backend"]["imgSaveBasePath"];
|
||||
//viewer
|
||||
auto viewerData = settingJson["ImageView"];
|
||||
auto viewerData = settingJson["ImageView"];
|
||||
for (auto data = viewerData.begin(); data != viewerData.end(); data++)
|
||||
{
|
||||
viewerStruct v;
|
||||
|
||||
@@ -2,6 +2,14 @@
|
||||
#include <QDebug>
|
||||
using namespace std;
|
||||
#include <QTextCodec>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
static std::atomic<bool> g_reconnecting(false);
|
||||
static std::mutex g_reconnect_mutex;
|
||||
|
||||
QByteArray mv_Status = "connected";//0106 新增相机断联报警
|
||||
long long index = 0; //相机序号
|
||||
void* handle;
|
||||
@@ -174,23 +182,47 @@ void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser)
|
||||
mv_Status = "disconnect";
|
||||
qDebug() << "[Error] " << " MV camera disconnects!";
|
||||
moduleStatus = false;
|
||||
|
||||
if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT)
|
||||
{
|
||||
//断开连接
|
||||
CloseDevice();
|
||||
handle = nullptr;
|
||||
BOOL bConnected = FALSE;
|
||||
while (1)
|
||||
// 如果已有重连线程在运行,则直接返回
|
||||
bool expected = false;
|
||||
if (!g_reconnecting.compare_exchange_strong(expected, true))
|
||||
{
|
||||
Sleep(100);
|
||||
if (connectDevice() == true)
|
||||
{
|
||||
qWarning() << "[Hd_CameraModule_HIK] " << " Hd_CameraModule_HIK create success again! ";
|
||||
moduleStatus = true;
|
||||
break;
|
||||
}
|
||||
|
||||
qDebug() << "[Info] reconnect already in progress";
|
||||
return;
|
||||
}
|
||||
|
||||
// 启动后台线程负责重连,避免在回调线程中长时间阻塞
|
||||
std::thread([]() {
|
||||
qDebug() << "[Info] start reconnect thread";
|
||||
|
||||
// 确保设备资源关闭
|
||||
CloseDevice();
|
||||
|
||||
int attempt = 0;
|
||||
int delay_ms = 500; // 初始延迟
|
||||
while (true)
|
||||
{
|
||||
attempt++;
|
||||
qDebug() << "[Info] reconnect attempt:" << attempt;
|
||||
if (connectDevice())
|
||||
{
|
||||
qWarning() << "[Hd_CameraModule_HIK] reconnect success!";
|
||||
moduleStatus = true;
|
||||
mv_Status = "connected";
|
||||
g_reconnecting = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// 指数退避,最大 5000ms
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
|
||||
delay_ms = delay_ms * 2;
|
||||
if (delay_ms > 5000) delay_ms = 5000;
|
||||
|
||||
// 在某些场景可能希望退出重连(例如程序关闭),如果未来需要可增加退出条件
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,11 +344,17 @@ Hd_CameraModule_HIK_hard_PCIE::Hd_CameraModule_HIK_hard_PCIE()
|
||||
void CloseDevice()
|
||||
{
|
||||
|
||||
unsigned int nRet = MV_CC_StopGrabbing(handle);
|
||||
CloseHandle(handle);
|
||||
//nRet = MV_CC_CloseDevice(handle);
|
||||
//nRet = MV_CC_DestroyHandle(handle);
|
||||
// 如果 handle 已经为空,直接返回
|
||||
if (handle == nullptr)
|
||||
return;
|
||||
|
||||
// 使用 SDK 正确的停止/关闭/销毁流程,避免使用 CloseHandle 等不匹配的 API
|
||||
MV_CC_StopGrabbing(handle);
|
||||
MV_CC_CloseDevice(handle);
|
||||
MV_CC_DestroyHandle(handle);
|
||||
handle = nullptr;
|
||||
}
|
||||
|
||||
Hd_CameraModule_HIK_hard_PCIE::~Hd_CameraModule_HIK_hard_PCIE()
|
||||
{
|
||||
CloseDevice();
|
||||
@@ -488,25 +526,9 @@ bool Hd_CameraModule_HIK_hard_PCIE::run()
|
||||
{
|
||||
m_flag = false;
|
||||
int mytime = 0;
|
||||
if (imgShouldGetIndex < imgShouldGetVec.size()) {
|
||||
if (imgShouldGetVec[imgShouldGetIndex] == 0) {
|
||||
n_mutex->lock();
|
||||
queuepic.push_back(cv::Mat(200, 200, CV_8UC3, cv::Scalar(0, 0, 255))); //返回空图
|
||||
std::cout << "red" << std::endl;
|
||||
n_mutex->unlock();
|
||||
imgShouldGetIndex++;
|
||||
return true;
|
||||
}
|
||||
imgShouldGetIndex++;
|
||||
}
|
||||
int cnt = 0;
|
||||
while (true)
|
||||
{
|
||||
/* if (moduleStatus == false || mytime++ > getImageTimeOut || ifBreak == true)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}*/
|
||||
n_mutex->lock();
|
||||
cnt++;
|
||||
if (queuepic.size() > 0)
|
||||
@@ -516,14 +538,14 @@ bool Hd_CameraModule_HIK_hard_PCIE::run()
|
||||
std::cout << "\n gotImg" << std::endl;
|
||||
break;
|
||||
}
|
||||
if (cnt > 25000) {
|
||||
if (cnt > 120) {
|
||||
queuepic.push_back(cv::Mat(250, 250, CV_8UC3, cv::Scalar(0, 255, 0))); //返回空图
|
||||
std::cout << "timeout" << std::endl;
|
||||
n_mutex->unlock();
|
||||
return true;
|
||||
}
|
||||
n_mutex->unlock();
|
||||
QThread::msleep(1);
|
||||
QThread::msleep(10);
|
||||
}
|
||||
//考虑到误触发、漏触发的图,在这里进行设置。
|
||||
//需要设置曝光时
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
#include <QDebug>
|
||||
using namespace std;
|
||||
#include <QTextCodec>
|
||||
#include <thread>
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
|
||||
QByteArray mv_Status = "connected";//0106 新增相机断联报警
|
||||
long long index = 0; //相机序号
|
||||
void* handle;
|
||||
@@ -9,6 +14,8 @@ string Username = "";
|
||||
bool m_flag = false;
|
||||
//MV_CC_DEVICE_INFO_LIST m_stDevList;//相机设备
|
||||
bool moduleStatus = true;
|
||||
static std::atomic<bool> g_reconnecting(false);
|
||||
static std::mutex g_reconnect_mutex;
|
||||
QQueue<cv::Mat> queuepic;
|
||||
//data == "rest_newProductIn"时要结束run;机台报警,取图超时,复位后重新拍的情况。
|
||||
bool ifBreak = false;
|
||||
@@ -168,29 +175,67 @@ void SetGain(float GainValue)
|
||||
MV_CC_SetFloatValue(handle, "Gain", GainValue);
|
||||
}
|
||||
|
||||
//关闭设备
|
||||
void CloseDevice()
|
||||
{
|
||||
// 如果 handle 已经为空,直接返回
|
||||
if (handle == nullptr)
|
||||
return;
|
||||
|
||||
// 使用 SDK 正确的停止/关闭/销毁流程,避免在回调或其他线程中出错
|
||||
MV_CC_StopGrabbing(handle);
|
||||
MV_CC_CloseDevice(handle);
|
||||
MV_CC_DestroyHandle(handle);
|
||||
handle = nullptr; //确保后续可以重新创建 handle
|
||||
}
|
||||
|
||||
//0518 断线重连
|
||||
void __stdcall ReconnectDevice(unsigned int nMsgType, void* pUser)
|
||||
{
|
||||
mv_Status = "disconnect";
|
||||
qDebug() << "[Error] " << " MV camera disconnects!";
|
||||
moduleStatus = false;
|
||||
|
||||
if (nMsgType == MV_EXCEPTION_DEV_DISCONNECT)
|
||||
{
|
||||
//断开连接
|
||||
CloseDevice();
|
||||
handle = nullptr;
|
||||
BOOL bConnected = FALSE;
|
||||
while (1)
|
||||
// 如果已有重连线程在运行,则直接返回
|
||||
bool expected = false;
|
||||
if (!g_reconnecting.compare_exchange_strong(expected, true))
|
||||
{
|
||||
Sleep(100);
|
||||
if (connectDevice() == true)
|
||||
{
|
||||
qWarning() << "[Hd_CameraModule_HIK] " << " Hd_CameraModule_HIK create success again! ";
|
||||
moduleStatus = true;
|
||||
break;
|
||||
}
|
||||
|
||||
qDebug() << "[Info] reconnect already in progress";
|
||||
return;
|
||||
}
|
||||
|
||||
// 启动后台线程负责重连,避免在回调线程中长时间阻塞
|
||||
std::thread([]() {
|
||||
qDebug() << "[Info] start reconnect thread";
|
||||
|
||||
// 确保设备资源关闭
|
||||
CloseDevice();
|
||||
|
||||
int attempt = 0;
|
||||
int delay_ms = 500; // 初始延迟
|
||||
while (true)
|
||||
{
|
||||
attempt++;
|
||||
qDebug() << "[Info] reconnect attempt:" << attempt;
|
||||
if (connectDevice())
|
||||
{
|
||||
qWarning() << "[Hd_CameraModule_HIK] reconnect success!";
|
||||
moduleStatus = true;
|
||||
mv_Status = "connected";
|
||||
g_reconnecting = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// 指数退避,最大 5000ms
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
|
||||
delay_ms = delay_ms * 2;
|
||||
if (delay_ms > 5000) delay_ms = 5000;
|
||||
|
||||
// 在某些场景可能希望退出重连(例如程序关闭),如果未来需要可增加退出条件
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,14 +353,6 @@ Hd_CameraModule_HIK_hard_PCIE::Hd_CameraModule_HIK_hard_PCIE()
|
||||
//m_thread = new MyThread;
|
||||
//m_mutex = new QMutex();
|
||||
}
|
||||
//关闭设备
|
||||
void CloseDevice()
|
||||
{
|
||||
MV_CC_StopGrabbing(handle);
|
||||
MV_CC_CloseDevice(handle);
|
||||
MV_CC_DestroyHandle(handle);
|
||||
handle = nullptr; //此处注释掉的话,软件断开再连接,回调函数不出图
|
||||
}
|
||||
Hd_CameraModule_HIK_hard_PCIE::~Hd_CameraModule_HIK_hard_PCIE()
|
||||
{
|
||||
CloseDevice();
|
||||
@@ -487,20 +524,8 @@ bool Hd_CameraModule_HIK_hard_PCIE::run()
|
||||
{
|
||||
m_flag = false;
|
||||
int mytime = 0;
|
||||
if (imgShouldGetIndex < imgShouldGetVec.size()) {
|
||||
if (imgShouldGetVec[imgShouldGetIndex] == 0) {
|
||||
n_mutex->lock();
|
||||
queuepic.push_back(cv::Mat(200, 200, CV_8UC3, cv::Scalar(0, 0, 255))); //返回空图
|
||||
std::cout << "red" << std::endl;
|
||||
n_mutex->unlock();
|
||||
imgShouldGetIndex++;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
MV_CC_SetCommandValue(handle, "TriggerSoftware");
|
||||
imgShouldGetIndex++;
|
||||
}
|
||||
int cnt = 0;
|
||||
MV_CC_SetCommandValue(handle, "TriggerSoftware");
|
||||
while (true)
|
||||
{
|
||||
/* if (moduleStatus == false || mytime++ > getImageTimeOut || ifBreak == true)
|
||||
@@ -517,14 +542,14 @@ bool Hd_CameraModule_HIK_hard_PCIE::run()
|
||||
std::cout << "\n gotImg" << std::endl;
|
||||
break;
|
||||
}
|
||||
if (cnt > 25000) {
|
||||
if (cnt > 120) {
|
||||
queuepic.push_back(cv::Mat(250, 250, CV_8UC3, cv::Scalar(0, 255, 0))); //返回空图
|
||||
std::cout << "timeout" << std::endl;
|
||||
n_mutex->unlock();
|
||||
return true;
|
||||
}
|
||||
n_mutex->unlock();
|
||||
QThread::msleep(1);
|
||||
QThread::msleep(10);
|
||||
}
|
||||
//考虑到误触发、漏触发的图,在这里进行设置。
|
||||
//需要设置曝光时
|
||||
|
||||
Reference in New Issue
Block a user