881 lines
32 KiB
C++
881 lines
32 KiB
C++
#include "Logic_taskthread.h"
|
|
#include <global.h>
|
|
//图像锁、通信指令锁
|
|
void Logic_taskthread::setMutex(QMutex* image_lock, QMutex* write_mutex) {
|
|
if (m_image_lock == nullptr)
|
|
m_image_lock = new QMutex;// image_lock;
|
|
if (write_data_mutex == nullptr)
|
|
write_data_mutex = write_mutex;
|
|
}
|
|
|
|
Logic_taskthread::Logic_taskthread(QObject *parent) :m_obj(parent)
|
|
{
|
|
task_image_lock = new QMutex;
|
|
}
|
|
|
|
Logic_taskthread::~Logic_taskthread()
|
|
{
|
|
m_stoprun = 0;
|
|
Sleep(100);
|
|
if (task_image_lock)
|
|
{
|
|
delete task_image_lock;
|
|
task_image_lock = nullptr;
|
|
}
|
|
|
|
Sleep(100);
|
|
wait(100);
|
|
exit();
|
|
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " delete thread success! ";
|
|
}
|
|
|
|
bool Logic_taskthread::initLogic_taskThread(QString task_name,QString stationName, QJsonObject array_obj,MyModule list)
|
|
{
|
|
try
|
|
{
|
|
m_name = task_name;
|
|
m_stationName = stationName;
|
|
|
|
m_exec_object = array_obj;
|
|
m_module = list;
|
|
|
|
} catch (QString ev) {
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " ev:" << ev;
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
//算法模块的结果要发送数据的,添加指令到容器
|
|
bool Logic_taskthread::appendPlcCmd(QJsonObject m_moduleobj)
|
|
{
|
|
QString algorithm_key = m_moduleobj.value("算法名称").toString(); // 算法名称
|
|
QJsonArray algorithm_result_array = m_moduleobj.value("算法结果列表").toArray();
|
|
|
|
if ( algorithm_result_array.isEmpty() )
|
|
{
|
|
qWarning() << __FUNCTION__ << " line:" << __LINE__ << " algorithm_result_array is null! ";
|
|
// return false;
|
|
}
|
|
else
|
|
{
|
|
QVector<send_algorithm_result> vector_send_algorithm_result;
|
|
for ( auto val = 0; val < algorithm_result_array.size(); val++ )
|
|
{
|
|
QJsonObject obj = algorithm_result_array.at(val).toObject();
|
|
QString key = obj.value("结果标志").toString();
|
|
//QString algorithm_complete_plcpos = obj.value("写PLC地址").toString();
|
|
|
|
QVector<QString> plc_commond_vector;
|
|
QJsonArray result_array = obj.value("结果内容").toArray();
|
|
//plc_commond_vector.push_back(algorithm_complete_plcpos); // 添加 结果拍照完成信号
|
|
|
|
//// 添加结果数据信息
|
|
//for ( int i = 0; i < result_array.size();i++ )
|
|
//{
|
|
// QString write_plcpos = result_array.at(i).toObject().value("write_plcpos").toString();
|
|
// if(!write_plcpos.isEmpty())
|
|
// plc_commond_vector.push_back(write_plcpos);
|
|
// /* else
|
|
// qWarning() << __FUNCTION__ << " line:" << __LINE__ << " warning write_plcpos is null!";*/
|
|
//}
|
|
|
|
//// 添加结果正负值信息
|
|
//for ( int i = 0; i < result_array.size();i++ )
|
|
//{
|
|
// QString write_plcpos = result_array.at(i).toObject().value("negative_plcpos").toString();
|
|
// if(!write_plcpos.isEmpty())
|
|
// plc_commond_vector.push_back(write_plcpos);
|
|
// // else
|
|
// // qWarning() << __FUNCTION__ << " line:" << __LINE__ << " warning negative_plcpos is null!";
|
|
//}
|
|
send_algorithm_result m_result;
|
|
m_result.key = key;
|
|
m_result.plc_commond_vector = plc_commond_vector;
|
|
|
|
vector_send_algorithm_result.push_back(m_result);
|
|
}
|
|
send_algorithm_result_to_plc_map.insert(algorithm_key,vector_send_algorithm_result);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
void Logic_taskthread::set_m_stoprun(bool myrun)
|
|
{
|
|
QMutexLocker locker(task_image_lock);
|
|
m_stoprun ++;
|
|
}
|
|
|
|
void Logic_taskthread::run()
|
|
{
|
|
try
|
|
{
|
|
processTask();
|
|
} catch ( QString ev ) {
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " ev:" << ev;
|
|
return;
|
|
}
|
|
}
|
|
//循环取检测数据,传到检测模块运行
|
|
bool Logic_taskthread::processTask()
|
|
{
|
|
clock_t start, stop;
|
|
start = clock();
|
|
m_stoprun++;
|
|
|
|
HStationData* station_ptr = station_list.value(m_stationName);
|
|
if (station_ptr)
|
|
{
|
|
//for ( int val = 0; val < m_module_list.size(); val++ )
|
|
{
|
|
QString m_key = m_module.module_key;
|
|
HAlgorithmExecData* m_ptr = station_ptr->getAlgorithmExecData(m_key);
|
|
if (m_ptr)
|
|
while (m_stoprun)
|
|
{
|
|
testData m_data; //SONY版放在while循环外,全是同一张图
|
|
if (m_ptr->getDetectData(m_data))
|
|
{
|
|
start = clock();
|
|
QVector<QString> camera_name = m_data.cameraName;
|
|
QVector<QString> task_index = m_data.task_index;
|
|
QVector<QString> camera_name_index;// = camera_name + "_" + task_index;
|
|
for (int i = 0; i < camera_name.size(); i++)
|
|
{
|
|
camera_name_index.append(camera_name[i] + "_" + task_index[i]);
|
|
//qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << "m_module.module_key:"<< m_module.module_key
|
|
// <<" checkImg getDetectData--CameraName:" << camera_name[i] << " imgIndex:" << task_index[i];
|
|
}
|
|
queue_exec_cameraName.append(m_data);
|
|
//or检测:保存路径,拍照面描述,相机key_第几张图,SN_时间戳
|
|
//and检测:保存路径,拍照面描述,相机key_第几张图,相机key_第几张图,SN_时间戳,SN_时间戳
|
|
//汇总:保存路径,拍照面描述,触发信号_序号列表0,,SN_时间戳
|
|
//m_data.byte
|
|
//std::cout << "camera_name_index[0]::" << camera_name_index[0].toStdString() << std::endl;
|
|
AlgorithmModuleProcessData(m_module.module_key, camera_name_index, m_data.dstImageMat, m_data.byteArray);
|
|
m_ptr->deleteDetectData();
|
|
/*stop = clock();
|
|
qDebug() << "m_module.module_key::" << m_module.module_key << " Logic_taskthread cut Time ::" << stop - start ;
|
|
start = clock();*/
|
|
}
|
|
else
|
|
Sleep(2);//避免软件卡顿
|
|
}
|
|
//stop = clock();
|
|
//qDebug() << "m_module.module_key::" << m_module.module_key << " Logic_taskthread cut Time ::" << stop - start ;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
//传递数据到检测/汇总模块,运行后,返回数据;按照需求,去发送结果给PLC、保存数据(汇总模块取出后汇总)
|
|
bool Logic_taskthread::AlgorithmModuleProcessData(QString key, QVector<QString> camera_name_index,std::vector<cv::Mat> vector_mat,QByteArray send_byte)
|
|
{
|
|
std::vector<cv::Mat> ai_mat;
|
|
QByteArray ai_byte;
|
|
clock_t start_time = 0;
|
|
clock_t stop_time = 0;
|
|
|
|
// 查找对应的模块名,和对应模块的object
|
|
//m_module = getExecModule(key);
|
|
if(m_module.module_key.contains("error"))
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " getExecModule is error!";
|
|
return false;
|
|
}
|
|
//当前算法的配置文件
|
|
//m_exec_object = getModuleObject(key);
|
|
if ( m_exec_object.isEmpty() )
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " m_exec_object is null!";
|
|
return false;
|
|
}
|
|
|
|
// 初始化
|
|
QJsonObject nullobj;
|
|
save_sn_info = nullptr;
|
|
save_data_flag = "false"; // 是否保存数据
|
|
send_data_flag = "false"; //是否发送数据
|
|
m_sn_set_object = nullobj; // 重置
|
|
m_name = m_exec_object.value("算法名称").toString();
|
|
m_type = "algorithm";// m_exec_object.value("type").toString();
|
|
save_data_flag = m_exec_object.value("是否保存数据").toString();
|
|
send_data_flag = m_exec_object.value("是否发送结果给PLC").toString();
|
|
m_sn_set_object = m_exec_object.value("SN设置").toObject();
|
|
if ( m_type.isEmpty() || m_name.isEmpty() || save_data_flag.isEmpty() )
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " m_type or m_name is null!";
|
|
}
|
|
// 发送图片和数据到算法
|
|
start_time = clock();
|
|
sendDataToModule(camera_name_index,vector_mat,send_byte);
|
|
|
|
//无法通过Base*继承QThread来实现
|
|
//注意,run函数应当以线程运行检测函数,sleep+计次的方式,判断moduleTimeout;超时给小线程退出标志,并返回false;
|
|
if (m_module.module_ptr->run() )//超时放入模块;模块超时,直接返回异常;927小图出现seg检测10秒
|
|
{
|
|
if ( !m_module.module_ptr->readData ( ai_mat,ai_byte ) )
|
|
{
|
|
//qCritical() << __FUNCTION__ << __LINE__ << " check ai module result is error! ";
|
|
vector_mat.clear();
|
|
ai_mat.clear();
|
|
return false;
|
|
}
|
|
// 保存算法图片
|
|
if(ai_byte.isEmpty())
|
|
addNGdata(ai_byte);
|
|
}
|
|
else
|
|
{
|
|
addNGdata(ai_byte);
|
|
|
|
}
|
|
stop_time = clock();
|
|
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " reciveImage to sendResult times :" << long(stop_time - start_time);
|
|
start_time = clock();
|
|
|
|
// 发送AI数据 和 图
|
|
if ( !ai_byte.isEmpty() )
|
|
{
|
|
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " send ai byte :" << ai_byte.length();
|
|
std::vector<cv::Mat> null_mat;
|
|
|
|
if (!ai_mat.empty())
|
|
null_mat = ai_mat;// .at(0);
|
|
//保存结果图到容器并UI显示;发送结果数据给PLC
|
|
sendDataCommond(m_type,camera_name_index,null_mat,ai_byte);
|
|
vector_mat.clear();
|
|
ai_mat.clear();
|
|
}
|
|
else
|
|
{
|
|
//qCritical() << __FUNCTION__ << " line:" << __LINE__ <<" m_name:" << m_name << " ai_byte len:" << ai_byte.length() << " error check data is null! ";
|
|
|
|
// 发送异常指令
|
|
//sendCatchCommond(camera_name_index);
|
|
|
|
std::vector<cv::Mat> null_mat;
|
|
sendDataCommond(m_type,camera_name_index,null_mat,"null"); // 发送异常信息到界面显示
|
|
}
|
|
stop_time = clock();
|
|
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " reciveImage to sendResult times2 :" << long(stop_time - start_time);
|
|
start_time = clock();
|
|
return true;
|
|
}
|
|
|
|
//检测超时或返回false,补NG结果
|
|
void Logic_taskthread::addNGdata(QByteArray& ai_byte)
|
|
{
|
|
QVector<QString> append_value;
|
|
for (auto vvv = 0; vvv < m_exec_object.value("算法结果列表").toArray().size(); vvv++)
|
|
{
|
|
QJsonObject obj = m_exec_object.value("算法结果列表").toArray().at(vvv).toObject();
|
|
QJsonArray algorithm_result= obj.value("结果内容").toArray();
|
|
for (int i = 0; i < algorithm_result.size(); i++)
|
|
{
|
|
QString ngdata = algorithm_result.at(i).toObject().value("超时补结果").toString();
|
|
append_value.append(ngdata);
|
|
}
|
|
}
|
|
if (append_value.size() > 0)
|
|
encodeAppendData(append_value, ai_byte);
|
|
}
|
|
|
|
|
|
//传递数据待检测/汇总模块
|
|
bool Logic_taskthread::sendDataToModule(QVector<QString> camera_name_index, std::vector<cv::Mat> vector_mat,QByteArray send_byte)
|
|
{
|
|
QString send_sn_flag = m_sn_set_object.value("检测-是否传递SN到算法模块").toString();
|
|
//for (int i = 0; i < camera_name_index.size(); i++)
|
|
{
|
|
//检测算法为true;汇总算法为false
|
|
if (send_sn_flag.contains("true"))
|
|
{
|
|
// 获取临时保存的当前的sn
|
|
save_sn_info= send_byte.split(',').last();// = getSnDataInfo(send_byte);
|
|
|
|
m_module.module_ptr->writeData(vector_mat, send_byte); // 传递图+相机名称+sn码信息
|
|
|
|
}
|
|
else
|
|
{
|
|
// 为不改动之前的算法处理方式,做了区分
|
|
if (send_byte.isEmpty())//考虑文件夹汇总?
|
|
{
|
|
//汇总,camera_name_index只有一个内容
|
|
QString camera_name = camera_name_index[0].split("_")[0];
|
|
if (!camera_name.isEmpty())
|
|
send_byte = camera_name.toUtf8();
|
|
|
|
m_module.module_ptr->writeData(vector_mat, send_byte);
|
|
}
|
|
else
|
|
{
|
|
m_module.module_ptr->writeData(vector_mat, send_byte); //汇总算法
|
|
}
|
|
}
|
|
}
|
|
|
|
if (save_sn_info.isEmpty())
|
|
Sleep(1);
|
|
return true;
|
|
}
|
|
|
|
QString Logic_taskthread::getSnDataInfo ( QByteArray byteArray )
|
|
{
|
|
if ( byteArray.isEmpty() )
|
|
return nullptr;
|
|
else
|
|
{
|
|
QByteArrayList vec_ret;
|
|
if ( decodeAiValue( byteArray, vec_ret ) )
|
|
{
|
|
if ( !vec_ret.isEmpty() )
|
|
{
|
|
return vec_ret.at(0);
|
|
}
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
//添加数据到最前面
|
|
bool Logic_taskthread::encodeAppendData(QVector<QString> append_value, QByteArray &byteArray)
|
|
{
|
|
try
|
|
{
|
|
QByteArray resultByte;
|
|
std::string sendMsg;
|
|
for (int i = 0; i < append_value.size(); i++)
|
|
{
|
|
std::string value = append_value.at(i).toStdString();
|
|
//type
|
|
int type = 3;
|
|
std::string m_type;
|
|
m_type.insert(0, 4, '1');
|
|
memcpy((void*)m_type.c_str(), (void*)&type, 4);
|
|
sendMsg.append(m_type);
|
|
|
|
//len
|
|
int len = value.length();
|
|
std::string m_len;
|
|
m_len.insert(0, 4, '1');
|
|
memcpy((void*)m_len.c_str(), (void*)&len, 4);
|
|
sendMsg.append(m_len);
|
|
|
|
//data x
|
|
sendMsg.append(value);
|
|
}
|
|
resultByte = QByteArray::fromStdString(sendMsg);
|
|
|
|
if (byteArray.isEmpty())
|
|
{
|
|
byteArray = resultByte;
|
|
}
|
|
else
|
|
{
|
|
byteArray = resultByte.append(byteArray);
|
|
}
|
|
}
|
|
catch (QString ev)
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " ev:" << ev;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Logic_taskthread::decodereciveValue(QByteArray byteArray, QVector<QByteArray>& vec_ret)
|
|
{
|
|
while (!byteArray.isEmpty())
|
|
{
|
|
int type = 0;
|
|
QByteArray m_type = byteArray.mid(0, 4);
|
|
memcpy((void*)&type, (void*)m_type.data(), 4);
|
|
byteArray.remove(0, 4);
|
|
|
|
int len = 0;
|
|
QByteArray m_len = byteArray.mid(0, 4);
|
|
memcpy((void*)&len, (void*)m_len.data(), 4);
|
|
byteArray.remove(0, 4);
|
|
|
|
QByteArray mm_data = byteArray.mid(0, len);
|
|
vec_ret.append(mm_data);
|
|
byteArray.remove(0, len);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
//保存算法结果数据到容器
|
|
bool Logic_taskthread::saveAlgorithmData(testData m_testdata, int index, QByteArray byteArray)
|
|
{
|
|
//for (int i = 0; i < m_testdata.cameraName.size(); i++)
|
|
{
|
|
QString camera_name = m_testdata.cameraName[index];
|
|
QString task_index = m_testdata.task_index[index];
|
|
|
|
Algorithm_Result_Data result_data;
|
|
result_data.byteArray = byteArray;
|
|
if (m_testdata.SN_dataTime.size())
|
|
result_data.SN_dataTime = m_testdata.SN_dataTime[0]; //这里暂时只取了第一个SN;即一张图对应一个SN;一张图里有2个产品的情况,应该在回调函数放两次图
|
|
|
|
//if (!result_data.SN_dataTime.contains("err"))
|
|
HAlgorithmData* algorithmPtr = station_list.value(m_stationName)->getAlgorithmData(m_name);
|
|
if (algorithmPtr)
|
|
{
|
|
//errSN_errDatatime
|
|
QString cameraName_and_index = camera_name + "_" + task_index;
|
|
algorithmPtr->addAlgorithmData(cameraName_and_index, result_data);
|
|
}
|
|
else
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " cameraPtr is null!";
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Logic_taskthread::sendCatchCommond(QVector<QString> camera_name_index)
|
|
{
|
|
if ( send_algorithm_result_to_plc_map.keys().contains(m_name) )
|
|
{
|
|
// 写入异常信息
|
|
std::vector<cv::Mat> vec_mat;
|
|
QVector<send_algorithm_result> vector_send_result = send_algorithm_result_to_plc_map.value(m_name);
|
|
send_algorithm_result m_send_unusual_result;
|
|
for ( int i = 0 ; i < vector_send_result.size();i++ )
|
|
{
|
|
send_algorithm_result m_result = vector_send_result.at(i);
|
|
|
|
QString camera_index_key = m_result.key;
|
|
for (int ci = 0; ci < camera_name_index.size(); ci++)
|
|
if(camera_index_key == camera_name_index[ci])
|
|
{
|
|
m_send_unusual_result = m_result;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(m_send_unusual_result.vector_algorithm_unusual_feedback_plcpos.isEmpty())
|
|
return false;
|
|
|
|
foreach ( QString send_unusual_result,m_send_unusual_result.vector_algorithm_unusual_feedback_plcpos )
|
|
{
|
|
QByteArray send_byte = nullptr;
|
|
send_byte = send_unusual_result.toUtf8();
|
|
QMutexLocker locker(write_data_mutex);
|
|
writeCommondPack.append(send_byte);
|
|
}
|
|
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " send catch success! ";
|
|
}
|
|
else
|
|
{
|
|
qWarning() << __FUNCTION__ << " line:" << __LINE__ << " algorithm_unusual_feedback_plcpos_map not find!";
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Logic_taskthread::decodeAiValue(QByteArray byteArray, QByteArrayList &vec_ret)
|
|
{
|
|
if(byteArray.isEmpty())
|
|
{
|
|
qCritical() << __FUNCTION__ << "line:" << __LINE__ << " byte is null!";
|
|
return false;
|
|
}
|
|
vec_ret = byteArray.split('#');
|
|
|
|
return true;
|
|
}
|
|
|
|
QVector<QString> Logic_taskthread::getWriteVector(QString &startPos,QMap<QString,QString> &map)
|
|
{
|
|
QVector<QString> vector_value;
|
|
if ( map.isEmpty() ){
|
|
qWarning() << __FUNCTION__ << " line:" << __LINE__ << " map is null!";
|
|
return vector_value;
|
|
}
|
|
|
|
startPos = map.firstKey(); // 第一个key 取出的为 DM101
|
|
int check_pos = 0;
|
|
while(!map.isEmpty()){
|
|
QString m_key = map.firstKey();
|
|
QString m_value = map.value(m_key);
|
|
|
|
QString lastpos = m_key.right(1);
|
|
if ( check_pos == 0 ){
|
|
check_pos = lastpos.toInt(); // 截取最后一位的值
|
|
vector_value.push_back(m_value); // 添加值
|
|
map.remove(m_key);
|
|
}else{
|
|
int m_lastpos = lastpos.toInt();
|
|
if ( m_lastpos == check_pos ){
|
|
// 先判断是否连续,不连续则退出,连续则添加
|
|
vector_value.push_back(m_value); // 添加值
|
|
map.remove(m_key);
|
|
}else{
|
|
break;
|
|
}
|
|
}
|
|
check_pos++; // 移动位置
|
|
}
|
|
return vector_value;
|
|
}
|
|
|
|
bool Logic_taskthread::writeTcpData(QMap<QString,QString> key_value)
|
|
{
|
|
try{
|
|
std::vector<cv::Mat> vec_mat;
|
|
while ( !key_value.isEmpty() ){
|
|
QString dm_startPos; // 起始位
|
|
//连续的寄存器,做拼接
|
|
QVector<QString> vector_value = getWriteVector(dm_startPos,key_value); //按照"结果内容"列表内容,寄存器、值
|
|
qDebug() << __FUNCTION__ << " line: " << __LINE__ << " dm_startPos: " << dm_startPos << " vector_value: " << vector_value;
|
|
//注意,支持short,string,float,double;
|
|
QByteArray write_byte = writeFormat(dm_startPos,vector_value);
|
|
QMutexLocker locker(write_data_mutex);
|
|
if (!writeCommondPack.contains(write_byte))
|
|
writeCommondPack.append(write_byte);//结果指令格式,为,例:write_short_DM3000_1;
|
|
/*QString key_complete_pos = m_exec_object.value("算法完成回复PLC指令").toString();
|
|
if (key_complete_pos.contains("_"))
|
|
{
|
|
QByteArray complete_cmd = key_complete_pos.toLocal8Bit();
|
|
writeCommondPack.append(complete_cmd);
|
|
}*/
|
|
}
|
|
QMutexLocker locker(write_data_mutex);
|
|
QString key_complete_pos = m_exec_object.value("算法完成回复PLC指令").toString();
|
|
if (key_complete_pos.contains("_"))
|
|
{
|
|
QByteArray complete_cmd = key_complete_pos.toLocal8Bit();
|
|
if (!writeCommondPack.contains(complete_cmd))
|
|
writeCommondPack.append(complete_cmd);
|
|
}
|
|
} catch (QString ev) {
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " writeTcpData is failed! ev:" << ev;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
QByteArray Logic_taskthread::writeFormat(QString startPos, QVector<QString> vector_value)
|
|
{
|
|
QByteArray byteArray;
|
|
QString write_format;
|
|
|
|
// 其他格式 按照 长度+数据写入 进行编码
|
|
QString sendData;
|
|
for(int i = 0 ; i < vector_value.size();i++)
|
|
{
|
|
sendData.append(vector_value.at(i));
|
|
if (i < vector_value.size() - 1)
|
|
sendData.append(","); //拼接,通信模块按照","分割
|
|
}
|
|
|
|
if (ifAddCmdHead == true)
|
|
write_format = CmdHeadShort + startPos + "_" + sendData;
|
|
else if(!startPos.isEmpty())
|
|
write_format = startPos + "_" + sendData;
|
|
else write_format = sendData;
|
|
|
|
byteArray = write_format.toLocal8Bit();
|
|
return byteArray;
|
|
}
|
|
//保存结果图到容器并UI显示;发送结果数据给PLC
|
|
bool Logic_taskthread::sendDataCommond( QString m_type, QVector<QString> camera_name_index, std::vector<cv::Mat> mat,QByteArray byteArray)
|
|
{
|
|
// 界面显示包
|
|
QMutexLocker locker(m_image_lock);
|
|
|
|
for (int ci = 0; ci < camera_name_index.size(); ci++)
|
|
{
|
|
testData m_exec_testData; // 当前执行算法的输出结果信息
|
|
if (!queue_exec_cameraName.isEmpty())
|
|
{
|
|
m_exec_testData = queue_exec_cameraName.dequeue(); //实际就是检测数据
|
|
//m_pack.cameraName = m_exec_testData.cameraName[ci];
|
|
}
|
|
|
|
if (m_exec_testData.SN_dataTime.isEmpty())
|
|
{
|
|
m_exec_testData.SN_dataTime .append( save_sn_info);
|
|
}
|
|
|
|
// 查看是否需要发送正常反馈信息
|
|
if (send_algorithm_result_to_plc_map.keys().contains(m_name))
|
|
{
|
|
std::vector<cv::Mat> vec_mat;
|
|
QVector<send_algorithm_result> vector_send_result = send_algorithm_result_to_plc_map.value(m_name);
|
|
send_algorithm_result m_send_usual_result;
|
|
for (int i = 0; i < vector_send_result.size(); i++)
|
|
{
|
|
send_algorithm_result m_result = vector_send_result.at(i);
|
|
|
|
QString camera_index_key = m_result.key;
|
|
if (camera_index_key == camera_name_index[ci])
|
|
{
|
|
m_send_usual_result = m_result;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!byteArray.contains("null"))
|
|
{
|
|
foreach(QString send_usual_result, m_send_usual_result.vector_algorithm_usual_feedback_plcpos)
|
|
{
|
|
QByteArray send_byte = nullptr;
|
|
send_byte = send_usual_result.toUtf8();
|
|
QMutexLocker locker(write_data_mutex);
|
|
writeCommondPack.append(send_byte);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//qWarning() << __FUNCTION__ << " line:" << __LINE__ << " algorithm_usual_feedback_plcpos_map not find!";
|
|
}
|
|
//保存检测模块返回的数据到内存
|
|
if (save_data_flag == "true")
|
|
{
|
|
//保存算法结果数据到容器
|
|
saveAlgorithmData(m_exec_testData, ci, byteArray);
|
|
}
|
|
|
|
// 发送检测模块的结果到PLC
|
|
if (send_data_flag == "true")
|
|
{
|
|
QString sbyte = byteArray;
|
|
//发送数据给PLC
|
|
if (!writeAiCommond(m_name, camera_name_index[ci], byteArray))
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " ---- writeAiCommond is failed!"<<" byte,"<< sbyte;
|
|
}
|
|
}
|
|
|
|
snInfo.clear();
|
|
sndata.clear();
|
|
send_ng_info.clear();
|
|
//汇总算法删除,检测算法不删。
|
|
//获取第一组sn;//获取次数是sn容器长度的倍数时,删一个数据
|
|
bool ifdeleSn = deleteSnData(byteArray, sndata, send_ng_info);
|
|
|
|
//汇总算法
|
|
// 传递给界面用来显示产品的sn码
|
|
QString read_sn_position = m_sn_set_object.value("汇总-读哪个SN").toString();
|
|
if (!read_sn_position.isEmpty())
|
|
{
|
|
int sn_index = read_sn_position.mid(2, read_sn_position.length()).toInt();
|
|
if ((sn_index > 0) && ((sn_index - 1) < sndata.length()))
|
|
{
|
|
snInfo = sndata.at(sn_index - 1);
|
|
}
|
|
}
|
|
|
|
dataPack m_pack;
|
|
if (mat.size() > ci)
|
|
{
|
|
if (mat[ci].data)
|
|
{
|
|
//if ((mat[ci].dataend - mat[ci].datastart)
|
|
// < mat[ci].cols * mat[ci].rows * mat[ci].channels()) //尝试能否解决mtx内容异常问题
|
|
//{
|
|
// qCritical() << __FUNCTION__ << " line:" << __LINE__ << " mtx.dataend - mtx.datastart err!!:";
|
|
// return false;
|
|
//}
|
|
}
|
|
else return false;
|
|
//if (mat[ci].cols > 2000 || mat[ci].rows > 2000)
|
|
// cv::resize(mat[ci], mat[ci], cv::Size(), 0.5, 0.5); //图像大时(内存、cpu占用大),耗时长。
|
|
m_pack.mat = mat[ci].clone();
|
|
}
|
|
m_pack.byteArray = byteArray;
|
|
m_pack.retFlag = m_type;
|
|
|
|
if (!queue_exec_cameraName.isEmpty())
|
|
{
|
|
//m_exec_testData = queue_exec_cameraName.dequeue(); //实际就是检测数据
|
|
m_pack.cameraName = m_exec_testData.cameraName[ci];
|
|
}
|
|
|
|
if (!snInfo.isEmpty())
|
|
{
|
|
m_pack.snInfo = snInfo;
|
|
}
|
|
else
|
|
{
|
|
m_pack.snInfo = save_sn_info;
|
|
}
|
|
|
|
if (send_ng_info.contains("send_ng_info"))
|
|
{
|
|
m_pack.sendNgInfo = send_ng_info;
|
|
}
|
|
if ((m_name == "2algorithm11" || m_name == "2algorithm12" || m_name == "4algorithm11" || m_name == "4algorithm12") && m_pack.snInfo.isEmpty())
|
|
std::cout << "task m_pack.snInfo.isEmpty()!" << std::endl;
|
|
m_pack.cameraName = camera_name_index[ci]; // 传递算法对应的相机名称
|
|
m_pack.algorithmName = m_name; // 传递算法名称
|
|
|
|
//if (m_pack.mat.data)
|
|
// if ((m_pack.mat.dataend - m_pack.mat.datastart)
|
|
// < m_pack.mat.cols * m_pack.mat.rows * m_pack.mat.channels()) //尝试能否解决mtx内容异常问题
|
|
// {
|
|
// qCritical() << __FUNCTION__ << " line:" << __LINE__ << " mtx.dataend - mtx.datastart err!!:";
|
|
// return false;
|
|
// }
|
|
//保存到容器,getdataPack主动取一个数据并显示到UI界面
|
|
Task_ImageDataPack.enqueue(m_pack);
|
|
|
|
|
|
/*stop_time = clock();
|
|
qDebug() << __FUNCTION__ << " line:" << __LINE__ << " m_name:" << m_name << " reciveImage to sendResult times5 :" << long(stop_time - start_time);
|
|
start_time = clock();*/
|
|
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Logic_taskthread::getdataPack(dataPack& myDataPack)
|
|
{
|
|
// 界面显示包
|
|
QMutexLocker locker(task_image_lock);
|
|
if (taskImageDataPack.size() > 0)
|
|
{
|
|
myDataPack = taskImageDataPack.dequeue();
|
|
return true;
|
|
}
|
|
else return false;
|
|
}
|
|
//汇总算法,删除SN,所有相机线程的snIndex减一
|
|
bool Logic_taskthread::deleteSnData ( QByteArray byteArray, QVector<QString>& sndata,QString &send_ng_info)
|
|
{
|
|
// 读取sn区域的位置下标;只在汇总算法有,检测算法无
|
|
QString read_sn_area_index = m_sn_set_object.value("汇总-读哪个上料通道的SN").toString();
|
|
if (read_sn_area_index.isEmpty())
|
|
{
|
|
return false;
|
|
}
|
|
// 删除sn码的标志;汇总算法为true
|
|
QString delete_sn_flag = m_sn_set_object.value("汇总-是否删除SN容器首数据").toString();
|
|
|
|
//HSnData根据sn_area数创建;多个算法的read_sn_area_index相同的,sn码指向同一个HSnData
|
|
int trueNum = 0;
|
|
for (int sk = 0; sk < summary_stationKeyS.size(); sk++)
|
|
{
|
|
HSnData* m_sndata = station_list.value(summary_stationKeyS[sk])->getSnInfoData(read_sn_area_index.toInt());
|
|
if (m_sndata)
|
|
{
|
|
if (!m_sndata->checkSnData()) //判断queue_vector_sn是否为空
|
|
{
|
|
//汇总算法为true,普通算法无
|
|
if (delete_sn_flag.contains("true"))
|
|
{
|
|
sndata = m_sndata->getFirstValue(); // 先获取再删除
|
|
if (m_sndata->removeOne())//删除queue_vector_sn一个;判断次数为queue_vector_sn的size时删除
|
|
{
|
|
m_sndata->setTaskDoneFlag(true);
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " station: "<< m_stationName<<" m_name: "<< m_module.module_key<<" allRunNum:"<< ++allRunNum;
|
|
|
|
trueNum++;
|
|
}
|
|
else
|
|
{
|
|
//return true;
|
|
trueNum++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sndata = m_sndata->getFirstValue();
|
|
/*if (sndata.isEmpty())
|
|
std::cout << "sndata .2." << std::endl;*/
|
|
//return true;
|
|
trueNum++;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
if (trueNum == summary_stationKeyS.size())
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
// 算法结果 写入plc
|
|
bool Logic_taskthread::writeAiCommond ( QString cameraName,QString camera_name_index,QByteArray byteArray )
|
|
{
|
|
std::string str = byteArray.toStdString();
|
|
int start = str.find(resultCmdSplitStart) + std::size(resultCmdSplitStart)-1;
|
|
int end = str.find(resultCmdSplitEnd)- start;
|
|
if (end > 0 && start > 0)
|
|
str = str.substr(start,end);
|
|
//char split = *generalSplit;
|
|
QByteArrayList PLCvec_ret= QByteArray::fromStdString(str).split(*generalSplit); // 存储结果的
|
|
|
|
if (PLCvec_ret.isEmpty() )
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " vec_ret is null!";
|
|
return false;
|
|
}
|
|
|
|
// 获取算法输出结果的信息
|
|
QJsonArray algorithm_result;
|
|
for ( auto vvv = 0; vvv < m_exec_object.value("算法结果列表").toArray().size(); vvv++ )
|
|
{
|
|
QJsonObject obj = m_exec_object.value("算法结果列表").toArray().at(vvv).toObject();
|
|
|
|
{
|
|
QString key = obj.value("结果标志").toString();
|
|
if ( camera_name_index== key ||
|
|
(key.split("_").size()==1 && camera_name_index.split("_")[0] == key)
|
|
|| key.contains("resultsSummary"))
|
|
{
|
|
algorithm_result = obj.value("结果内容").toArray();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
//检测模块返回的数据按照'#'分割,数据长度和配置文件的"算法结果列表"长度相匹配
|
|
//不匹配导致不发结果给PLC
|
|
if ( algorithm_result.size() > PLCvec_ret.length() )
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " algorithm_result != vec_ret failed! "<< camera_name_index;
|
|
PLCvec_ret.clear();
|
|
return false;
|
|
}
|
|
//qCritical() << __FUNCTION__ << " line:" << __LINE__ << " algorithm_result != vec_ret success! " << camera_name_index;
|
|
QMap<QString,QString> key_value;
|
|
|
|
for(int i = 0; i < algorithm_result.size(); i++)
|
|
{
|
|
QString key_dmpos = algorithm_result.at(i).toObject().value("写PLC地址").toString();
|
|
key_value.insert(key_dmpos, PLCvec_ret.at(i));
|
|
}
|
|
|
|
if ( !writeTcpData(key_value) )
|
|
{
|
|
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " writeTcpData failed!";
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
//获取一个数据包,并删除列表的头一个
|
|
dataPack Logic_taskthread::getdataPack()
|
|
{
|
|
QMutexLocker locker(m_image_lock); // 加锁
|
|
dataPack m_pack = Task_ImageDataPack.dequeue();
|
|
return m_pack;
|
|
}
|
|
int Logic_taskthread::dataPack_size()
|
|
{
|
|
QMutexLocker locker(m_image_lock); // 加锁
|
|
return Task_ImageDataPack.size();
|
|
} |