#include #include #include #include #include #include triggerManager::triggerManager(ServiceManager* _serviceManager, bSignalHub* bridgeIn,nlohmann::ordered_json& triggerJson){ bridge = bridgeIn; dManager = _serviceManager->_detDataManager; _cameraManager = _serviceManager->_cameraManager; for (auto& d : triggerJson["readAllCmd"]) { readAllStruct _struct; _struct.readAllCmd = QByteArray::fromStdString(d); auto splitResult = QString::fromStdString(d).split("_"); _struct.startPos = splitResult[2].split("D")[1].toInt(); _struct.readLength = splitResult[3].toInt(); readAllCmds.push_back(_struct); } triggerFileName = QString::fromStdString(triggerJson["moduleName"]); IpAndPort = QString::fromStdString(triggerJson["initStr"]); heartBeatIntervalMS = triggerJson.value("heartBeatIntervalMS",1); sleepIntervalMS = triggerJson.value("sleepIntervalMS", 1); std::vector heartbeats = triggerJson["heartBeatCmd"]; for (auto& cmd : heartbeats) { heartBeatCmds.push_back(QString::fromStdString(cmd)); } } void triggerManager::run(){ if(connectHost() == false) return; QThread::msleep(500); QElapsedTimer heartTimer, loopCounterCollectTimer,loopIntervalTimer; int loopCounter = 0,maxIntervalLog = 0,interval = 0; loopIntervalTimer.start(); while (runFlag){ reciveCommond(); if (heartTimer.elapsed()> heartBeatIntervalMS) {//心跳 sendFinsMsg(heartBeatCmds[heartBeatCmdCnt++]); if(heartBeatCmdCnt >= heartBeatCmds.size()) heartBeatCmdCnt = 0; heartTimer.start(); } if (loopCounterCollectTimer.elapsed() > 3000) {//发送性能数据 emit bridge->sendTriggerManagerLoopData(loopCounter / 3, maxIntervalLog); maxIntervalLog = 0; loopCounter = 0; loopCounterCollectTimer.start(); } loopCounter++; QThread::msleep(qMax(0, sleepIntervalMS - (int)loopIntervalTimer.elapsed())); maxIntervalLog = qMax(maxIntervalLog, (int)loopIntervalTimer.restart()); } } bool triggerManager::connectHost(){ if (init == true) return true; status = NotInit; m_lib = new QLibrary(triggerFileName); libLoadedflag = m_lib->load(); if (!m_lib->isLoaded()){ //emit _core._qtFunc.sendErrorToMainwindow(dllNotFound); emit bridge->loadingWindow_appendInitLog("找不到" + triggerFileName,"red"); return false; } if (libLoadedflag){ CreateRpcModuleBaseFunction createFun = (CreateRpcModuleBaseFunction)m_lib->resolve("create"); ReleaseRpcModuleBaseFunction releaseFun = (ReleaseRpcModuleBaseFunction)m_lib->resolve("destory"); bool initFailure = false; if (createFun && releaseFun) { trigger = createFun(); destoryRpcFunc = releaseFun; trigger->writeData(vec_mat, QByteArray(IpAndPort.toUtf8())); initFailure = trigger->initParas(QByteArray()); emit bridge->loadingWindow_appendInitLog(triggerFileName + "连接到" + IpAndPort,"white"); } if (initFailure == false){ //emit _core._qtFunc.sendErrorToMainwindow(triggerInitFailure); delete m_lib; m_lib = nullptr; emit bridge->loadingWindow_appendInitLog(triggerFileName + "初始化失败","red"); status = InitFailure; return false; } else{ status = InitOK; init = true; emit bridge->loadingWindow_appendInitLog(triggerFileName + "连接成功","green"); return true; } } return false; } void triggerManager::reciveCommond() { for (auto& _struct : readAllCmds) { QByteArray readByte = _struct.readAllCmd; mutex.lock(); if (!reciveFinsMsg(readByte)) qCritical() << "[TCP] " << " finstcp_ptr readData error!"; mutex.unlock(); tLocker[_struct.readAllCmd].reFreshLocker(readByte);//经过检查后再触发 decodeCameraCMD(_struct,readByte); } } void triggerManager::decodeCameraCMD(readAllStruct& _struct, QByteArray byte) { if (byte.isEmpty()) { 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=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 << "错误类型:大小不匹配"<< byte.toStdString() << std::endl; } if (lostConnectionRePrintTimer.elapsed() > 1000) { qCritical() << "ERROR:cant read data from Fins data sizesetPlcConnectionError(); isConnected = false; lostConnectionRePrintTimer.start(); } return; } else if (isConnected == false) { emit bridge->setPlcConnectionOk(); isConnected = true; qDebug() << "掉线时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒"; std::cout << "重连成功,经过时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒" << std::endl; } checkCallback(_struct,byte); checkUnionCallback(_struct, byte); checkPlcValueViewer(_struct, byte); } void triggerManager::checkCallback(readAllStruct _struct, QByteArray& byteArray) {//检查是否符合回调函数的触发条件 QMutexLocker locer(&mutex); for (auto callback : triggerCallbackFuncs[_struct.readAllCmd]) { if (checkTrigger(callback.triggerAddress, callback.triggerValue, _struct, byteArray) == true) { qDebug() << "func:" << QString::fromStdString(callback.funcName) << "->已触发 " << callback.triggerValue; std::thread([callback, byteArray]() mutable { try { callback.func(callback.triggerAddress, callback.triggerValue, byteArray); // 执行回调函数 } catch (const std::exception& e) { std::cerr << "Error in callback " << callback.funcName << ": " << e.what() << std::endl; } }).detach(); } } } void triggerManager::checkUnionCallback(readAllStruct& _struct, QByteArray& byteArray) { QMutexLocker locer(&mutex); auto it = unionTriggerCallbackFuncs.find(_struct.readAllCmd); if (it == unionTriggerCallbackFuncs.end()) return; auto& vec = it->second; for (auto& cb : vec) { if (cb.triggerAddressAndValue.empty()) continue; bool matched = false; std::vector> triggerSource; if (cb.mode == conditionMode:: or ) { // 任意一个满足即可 for (auto& cond : cb.triggerAddressAndValue) { if (checkTrigger(cond.first, cond.second, _struct, byteArray, true)) { // 不加锁,先判断 matched = true; triggerSource.push_back(cond); } else triggerSource.push_back({ cond.first ,INT_MIN });// 不满足的标记为 INT_MIN } } else { // AND 模式 matched = true; for (auto& cond : cb.triggerAddressAndValue) { if (!checkTrigger(cond.first, cond.second, _struct, byteArray, true)) { matched = false; break; } } triggerSource = cb.triggerAddressAndValue; // 全部都符合 } if (!matched) continue; // 再次对匹配条件加锁,防止重复触发 for (auto& cond : cb.triggerAddressAndValue) { int triggerPos = (cond.first - _struct.startPos) * 2 + 1; if (triggerPos >= 0 && triggerPos < byteArray.size()) { // 只有当前值仍符合才加锁 if (byteArray.at(triggerPos) == cond.second) { tLocker[_struct.readAllCmd].addLocker(triggerPos, cond.second); } } } qDebug() << "Union func:" << QString::fromStdString(cb.funcName) << "->已触发 ("<< triggerSource <<")"; std::thread([cb, copyByte = byteArray, triggerSource]() mutable { try { cb.func(triggerSource, copyByte); } catch (const std::exception& e) { std::cerr << "Error in union callback " << cb.funcName << ": " << e.what() << std::endl; } }).detach(); } } bool triggerManager::checkTrigger(int dmPos, int value, readAllStruct& _struct, QByteArray& byte, bool lockerDisable) { int triggerPos = (dmPos - _struct.startPos) * 2 + 1; if (byte.size() < triggerPos) return false; if (byte.at(triggerPos) == value) { if (tLocker[_struct.readAllCmd].checkLocker(triggerPos) == false) return false; if (lockerDisable == false) tLocker[_struct.readAllCmd].addLocker(triggerPos, value); return true; } else return false; } void triggerManager::checkPlcValueViewer(readAllStruct& _struct, QByteArray& byteArray) { QMutexLocker locer(&mutex); for (auto& data : plcValueViewerDatas) { int checkPos = (data.valueAddr - _struct.startPos) * 2 + 1; if (checkPos < byteArray.size() && checkPos >= 0) { QVariant newValue; if (data.type == finsFloat) newValue = readFinsFloatFromQByteArray(byteArray, checkPos, true); else newValue = byteArray.at(checkPos); if (newValue != data.value) { data.value = newValue; if (data.type == finsFloat) emit bridge->runCommand_refeshPlcValueViewer(data.valueAddr, QString::number(data.value.toDouble(), 'f', 4)); else emit bridge->runCommand_refeshPlcValueViewer(data.valueAddr, data.value.toString()); } } } }