277 lines
11 KiB
C++
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());
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|