Files
eUi/src/core/service/triggerManager.cpp
T
RCiRoot 95fd2cd89b V20260105-2.3.4
进一步优化rpcFIns的boost模块性能(测试)。
对赢合取图丢弃的逻辑进行了更改。
2026-01-05 01:05:56 +08:00

264 lines
11 KiB
C++

#include <triggerManager.h>
#include <detData.h>
#include <cameraManager.h>
#include <backendInterface.h>
#include <generalJsonParsing.hpp>
#include <serviceManager.h>
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<std::string> 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 size<preset,无法从fins读取数据 数据大小不匹配";
emit bridge->setPlcConnectionError();
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<std::pair<int, int>> 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());
}
}
}
}