Files
eUi/src/Core/back/triggerManager.h
T

367 lines
13 KiB
C++

#include <qdebug.h>
#include <qthread.h>
#include <subModuleBase.h>
#include <qlibrary.h>
#include <global.h>
#include <backStruct.h>
#include <functional>
#include <serviceModule.h>
#include <nlohmannJson.hpp>
#include <qelapsedtimer.h>
#define switchToRpc 1
#define debugTesting 0
using triggerCallback = std::function<void(int,int,QByteArray& byte)>;
class cameraManager;
class detThreadManager;
class detDataManager;
class lightSourceManager;
class detProcess;
//防止重复触发
class triggerLockerT {
public:
// 不存在则返回true
bool checkLocker(int pos) const {
return lockerVec.find(pos) == lockerVec.end();
}
// 如果和加锁的值不同则删除
void reFreshLocker(const QByteArray& input) {
for (auto it = lockerVec.begin(); it != lockerVec.end(); ) {
if (it->first >= input.size() || input.at(it->first) != it->second) {
it = lockerVec.erase(it); // erase 返回下一个迭代器
}
else {
++it;
}
}
}
// 添加锁
void addLocker(int pos, int val) {
lockerVec[pos] = val;
}
private:
std::unordered_map<int, int> lockerVec;
};
//触发器类 fins触发 tcp触发等 替代myiothread
class triggerManager : public serviceModule
{
public:
struct readAllStruct {
QByteArray readAllCmd;
int startPos;
int readLength;
};
std::vector<readAllStruct> readAllCmds;
//QByteArray readAllCmd;
QString triggerFileName;
QString IpAndPort;
QString triggerInitStr;
~triggerManager(){
runFlag = false;
this->stop();
this->terminate();
delete trigger;
}
triggerManager(detProcess*, qtFuncBridge* bridgeIn, nlohmann::ordered_json& triggerJson);
bool connectHost();
void run();
void stop(){
runFlag = false;
this->terminate();
}
#pragma region 发送数据
bool sendFinsMsg(QString cmdx){
if (trigger == nullptr)
return false;
if (!trigger->writeData(vec_mat, cmdx.toUtf8()))
{
qCritical() << "[TCP Error] " << QString::fromUtf8("Fins数据发送失败!") << cmdx;
return false;
}
return true;
}
bool sendFinsMsg(const char* cmdx){
QString str = cmdx;
if (trigger == nullptr)
return false;
if (!trigger->writeData(vec_mat, str.toUtf8()))
{
qCritical() << "[TCP Error] " << QString::fromUtf8("Fins数据发送失败!") << cmdx;
return false;
}
return true;
}
bool sendFinsMsg(QByteArray write_byte){
if (trigger == nullptr)
return false;
if (!trigger->writeData(vec_mat, write_byte) && trigger != nullptr)
{
qCritical() << "[TCP Error] " << QString::fromUtf8("Fins数据发送失败!") << write_byte;
return false;
}
return true;
}
//FINS
//useage "D9200_1"
bool writeShort(QByteArray write_byte) {
if (trigger == nullptr)
return false;
QByteArray array("write_short_" + write_byte);
if (!trigger->writeData(vec_mat, array) && trigger != nullptr)
{
qCritical() << "[TCP Error] " << QString::fromUtf8("Fins数据发送失败!") << write_byte;
return false;
}
return true;
}
//useage {"D9200_1","D9201_1"}
bool writeShort(std::vector<std::string> write_byte) {
if (trigger == nullptr)
return false;
for (auto& byteArray : write_byte) {
QByteArray array = QByteArray::fromStdString("write_short_" + byteArray);
if (!trigger->writeData(vec_mat, array) && trigger != nullptr) {
qCritical() << "[TCP Error] " << QString::fromUtf8("Fins数据发送失败!") << array;
return false;
}
}
return true;
}
//useage {"D9200_1","D9201_1"}
bool writeFloat(std::vector<std::string> write_byte) {
if (trigger == nullptr)
return false;
for (auto& byteArray : write_byte) {
QByteArray array = QByteArray::fromStdString("write_float_" + byteArray);
if (!trigger->writeData(vec_mat, array) && trigger != nullptr) {
qCritical() << "[TCP Error] " << QString::fromUtf8("Fins数据发送失败!") << array;
return false;
}
}
return true;
}
bool writeFloat(QByteArray write_byte) {
if (trigger == nullptr)
return false;
QByteArray array = "write_float_" + write_byte;
if (!trigger->writeData(vec_mat, array) && trigger != nullptr) {
qCritical() << "[TCP Error] " << QString::fromUtf8("Fins数据发送失败!") << array;
return false;
}
return true;
}
bool writeFloat(std::vector<QByteArray> write_byte) {
if (trigger == nullptr)
return false;
for (auto& byteArray : write_byte) {
QByteArray array = "write_float_" + byteArray;
if (!trigger->writeData(vec_mat, array) && trigger != nullptr) {
qCritical() << "[TCP Error] " << QString::fromUtf8("Fins数据发送失败!") << array;
return false;
}
}
return true;
}
#pragma endregion
#pragma region 接收数据
void reciveCommond();
//int read(int dmPos, QByteArray byte)
//{
// int triggerPos = (dmPos - startPos) * 2;
// if (byte.size() < triggerPos)
// return false;
// int val1 = byte.at(triggerPos) * 256;
// int val2 = static_cast<unsigned char>(byte.at(triggerPos + 1));
// return val1 + val2;
//}
QVariant read(int dmPos) {
QByteArray readByte;
mutex.lock();
if (!sendFinsMsg("read_byte_D" + QString::number(dmPos) + "_2"))
qCritical() << "[TCP] " << " finstcp_ptr reciveData error!";
if (!reciveFinsMsg(readByte))
qCritical() << "[TCP] " << " finstcp_ptr readData error!";
mutex.unlock();
int val1 = readByte.at(0) * 256;
int val2 = static_cast<unsigned char>(readByte.at(1));
return val1 + val2;
}
#pragma endregion
//CALL BACK
struct triggerCallbackStruct{
int triggerAddress;
int triggerValue;
triggerCallback func;
std::string funcName;
};
bool registerCallback(int triggerAddress, int triggerValue, triggerCallback func, std::string funcName =""){
triggerCallbackStruct _triggerCallbackStruct;
_triggerCallbackStruct.triggerAddress = triggerAddress;
_triggerCallbackStruct.triggerValue = triggerValue;
_triggerCallbackStruct.func = func;
_triggerCallbackStruct.funcName = funcName;
for (auto& _struct : readAllCmds) {
if (triggerAddress >= _struct.startPos && triggerAddress < _struct.startPos + _struct.readLength) {
triggerCallbackFuncs[_struct.readAllCmd].push_back(_triggerCallbackStruct);
return true;
}
}
qCritical() << "触发器回调地址超限了" << triggerAddress << triggerValue;
return false;
}
std::map<QByteArray, std::vector<triggerCallbackStruct>> triggerCallbackFuncs;
void checkCallbackAndTrigger(readAllStruct& _struct,QByteArray & byteArray){//检查是否符合回调函数的触发条件
for (auto callback : triggerCallbackFuncs[_struct.readAllCmd])
{
if (checkTrigger(callback.triggerAddress, callback.triggerValue, _struct, byteArray) == true)
{
qDebug() << "func:" << QString::fromStdString(callback.funcName) << "->已触发";
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();
}
}
}
std::string readSnFromQByteArray(QByteArray plcByte, int dmPos,
bool highLowConversion, bool clearAfterRead, int Size){
int startPos = 0;
for (auto& _struct : readAllCmds) {
if (dmPos > _struct.startPos &&
dmPos < _struct.startPos + _struct.readLength)
startPos = _struct.startPos;
}
if (startPos == 0) {
qCritical() << "读条码越界";
return "ERROR_OUT_OF_RANGE";
}
int triggerPos = (dmPos - startPos) * 2;
if (triggerPos < 0){
std::cout << "Read SN error,trigger is DM:" << dmPos << ",but read start at DM:" << startPos << endl;
return "snErrorsnError" + getCurrentDateTime();
}
QString str;
if (plcByte.at(triggerPos + 1) == 0 && plcByte.at(triggerPos) == 0)
return "snErrorsnError" + getCurrentDateTime();
int snCount = 0;
if (highLowConversion == true){
while (plcByte.at(snCount + triggerPos) != 0 || plcByte.at(snCount + triggerPos + 1) != 0){
if (plcByte.at(snCount + triggerPos) != 0)
str += QChar(plcByte.at(snCount + triggerPos));
snCount++;
}
}
else{
while (plcByte.at(snCount + triggerPos) != 0 || plcByte.at(snCount + triggerPos + 1) != 0){
if (plcByte.at(snCount + triggerPos + 1) != 0)
str += QChar(plcByte.at(snCount + triggerPos + 1));
if (plcByte.at(snCount + triggerPos) != 0)
str += QChar(plcByte.at(snCount + triggerPos));
snCount += 2;
}
}
if (str.size() < Size && Size != -1)
return "snErrorsnError" + getCurrentDateTime();
//if (clearAfterRead == true)
// //for(int i=0;i< snCount;i++)
// bridge.back.sendFinsMsg(
//QString::fromStdString("writeALL_DM" + to_string(dmPos) + "_" + to_string(snCount) + "_0"));
return str.toStdString();
}
private:
QElapsedTimer lostConnectionCountTimer,lostConnectionRePrintTimer;
qtFuncBridge* bridge;
bool libLoadedflag = false;
QLibrary* m_lib = nullptr;
detProcess* _detProcess;
lightSourceManager* _lightSourceManager;
detThreadManager* _threadManager;
detDataManager* dManager;
cameraManager* _cameraManager;
std::map<QByteArray,triggerLockerT> tLocker;//防止重复触发,每次收到数据时检查数据是否与上次相同,如果相同checkTrigger会返回false
/// <summary>
/// 检测QByteArray中某位置的值是否和输入一样,使用了绝对位置
/// </summary>
/// <param name="dmPos">绝对位置</param>
/// <param name="value">值</param>
/// <param name="byte">QByteArray</param>
/// <returns></returns>
bool checkTrigger(int dmPos, int value, readAllStruct& _struct, QByteArray& byte, bool lockerDisable = false){
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;
}
bool checkTrigger_Unsafe(int dmPos, int value, readAllStruct& _struct, QByteArray& byte, bool lockerDisable = false) {
int triggerPos = (dmPos - _struct.startPos) * 2 + 1;
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;
}
//接受数据
bool reciveFinsMsg(QByteArray& readByte){
if (!trigger->readData(vec_mat, readByte))
{
qCritical() << "[TCP] " << " finstcp_ptr readData error!";
return false;
}
return true;
}
QMutex mutex; //互斥锁,防止多线程访问冲突
//解析并触发
void decodeCameraCMD(readAllStruct&,QByteArray byte);
//触发器的配置
int sleepIntervalMS = 50;//间隔
int heartBeatIntervalMS = 800;
int heartBeatCmdCnt = 0;
std::vector<QString> heartBeatCmds;
#if switchToRpc==0
ReleaseFunction destory_finstcp; //释放
dsModuleBase* trigger = nullptr;
#else
ReleaseRpcModuleBaseFunction destory_finstcp; //释放
rpcModuleBase* trigger = nullptr;
#endif
bool isConnected = true;
bool runFlag = true;
bool init = false;
std::vector<cv::Mat> vec_mat;//没啥用,一直保持为空就好
};
#pragma once