Files
eUi/src/core/service/triggerManager.cpp
T
RCiRoot ee97a4ab2c V20260507-2.5.3
丰富了实时翻译词库,在更多的界面提供了翻译支持。
增加了在后端可以使用临时账户登录的功能。
增加了自动删除超期的日志文件以及自动删除超期的存图路径数据库。
2026-06-03 08:54:01 +08:00

277 lines
11 KiB
C++

#include <triggerManager.h>
#include <detData.h>
#include <cameraManager.h>
#include <backendInterface.h>
#include <generalJsonParsing.hpp>
#include <serviceManager.h>
#include <future>
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.insert(_struct.readAllCmd,_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){
receiveCommand();
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;
#if offlineMode == 0
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;
}
}
#else
status = InitOK;
init = true;
emit bridge->loadingWindow_appendInitLog("离线模式创建成功", "green");
#endif
return false;
}
void triggerManager::receiveCommand() {
#if offlineMode == 0
for (auto& _struct : readAllCmds) {
QByteArray readByte = _struct.readAllCmd;
//接收数据
{
QMutexLocker locker(&mutex);
if (!reciveFinsMsg(readByte))
qCritical() << "[TCP] " << " finstcp readData error!";
}
tLocker[_struct.readAllCmd].reFreshLocker(readByte);//经过检查后再触发
//解析数据
decodeCameraCMD(_struct,readByte);
}
#endif
}
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;
try {
callback.func(callback.triggerAddress, callback.triggerValue, byteArray); // 执行回调函数
}
catch (const std::exception& e) {
qCritical() << "Error in callback " << QString::fromStdString(callback.funcName) << ": " << QString::fromStdString(e.what());
}
catch (...) {
qCritical() << "Error in callback : unexpected" << QString::fromStdString(callback.funcName);
};
}
}
}
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 <<")";
try {
cb.func(triggerSource, byteArray);
}
catch (const std::exception& e) {
qCritical() << "Error in union callback " << QString::fromStdString(cb.funcName) << ": " << QString::fromStdString(e.what()) ;
}
catch (...) {
qCritical() << "Error in union callback : unexpected" << QString::fromStdString(cb.funcName);
};
}
}
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());
}
}
}
}