csv表格功能完善,以极性为示例
This commit is contained in:
@@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
|
||||
set(DLL_NAMES "opencv" "halcon" "halconAlgo""myTools" )
|
||||
set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" "handdleAI")
|
||||
foreach(child ${DLL_NAMES})
|
||||
LIST(APPEND ENV_INCLUDE ${${child}_include})
|
||||
LIST(APPEND ENV_LIB ${${child}_lib})
|
||||
@@ -39,7 +39,7 @@ FILE(GLOB UI_FILES "./*.ui")
|
||||
#find_package(Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
|
||||
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED)
|
||||
add_library(${CURRENT_FOLDER} SHARED
|
||||
${HEAD_FILES}
|
||||
${SRC_FILES}
|
||||
@@ -58,6 +58,7 @@ set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C
|
||||
target_link_libraries(${CURRENT_FOLDER} PRIVATE
|
||||
${ENV_TARGET}
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,103 +1,151 @@
|
||||
#include "Hd_AI_algo_jixing_L.h"
|
||||
#include "Hd_AI_algo_jiXing_L.h"
|
||||
#include <QDateTime>
|
||||
#include <codecvt>
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <qfuture.h>
|
||||
#include <QTextCodec>
|
||||
#include <corecrt_wstring.h>
|
||||
#include <myTools.h>
|
||||
#include <filesystem>
|
||||
#include <myTools.h>
|
||||
#include <algo.h>
|
||||
#include <global.h>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
//原图保存文件夹
|
||||
QString oriImgSaveDir = "D:/D601线/超声波预焊机/极性检测CCD/原图/";
|
||||
QString resultPlc;
|
||||
//原图保存文件夹s
|
||||
QString oriImgSaveDir = "D:/601线/终焊CCD/极性检测CCD/原图/";
|
||||
//原图class图保存文件夹
|
||||
QString classImgSaveDir = "D:/D601线/超声波预焊机/极性检测CCD/class图/";
|
||||
QString classImgSaveDir = "D:/601线/终焊CCD/极性检测CCD/class图/";
|
||||
//结果保存文件夹
|
||||
QString resImgSaveDir = "D:/D601线/超声波预焊机/极性检测CCD/结果图/";
|
||||
|
||||
QString resImgSaveDir = "D:/601线/终焊CCD/极性检测CCD/结果图/";
|
||||
int algoResult = 0;//0 OK 1 NG
|
||||
//切图的class的width,根据项目实际设置!
|
||||
int sizeW = 150;
|
||||
int sizeW = 150;
|
||||
//切图的class的height,根据项目实际设置!
|
||||
int sizeH = 150;
|
||||
int sizeH = 150;
|
||||
//切图的class的width,根据项目实际设置!0为黑,255为白;
|
||||
int fillColour = 0;
|
||||
int algoResult;
|
||||
int fillColour = 0;
|
||||
|
||||
|
||||
//检测线程锁
|
||||
QMutex* detect_mutex;
|
||||
QMutex* detect_mutex;
|
||||
//保存线程锁
|
||||
QMutex* saveStruct_mutex;
|
||||
QMutex* saveStruct_mutex;
|
||||
//检测线程运行标志
|
||||
bool ifdetectThread = false;
|
||||
bool ifdetectThread = false;
|
||||
|
||||
QString cameraKey_index = "";
|
||||
QString cameraKey_index = "";
|
||||
|
||||
//初始化参数列表
|
||||
QByteArrayList initValueList;
|
||||
static void createDirectoryIfNotExists(const QString& path) {
|
||||
QDir dir;
|
||||
dir.mkpath(path);
|
||||
}
|
||||
static std::string getCurrentTime() {
|
||||
//初始化参数列表
|
||||
QByteArrayList initValueList;
|
||||
|
||||
// 获取当前时间点
|
||||
auto now = std::chrono::system_clock::now();
|
||||
static void createDirectoryIfNotExists(const QString& path) {
|
||||
QDir dir;
|
||||
dir.mkpath(path);
|
||||
}
|
||||
static std::string getCurrentTime() {
|
||||
|
||||
// 转换为字符串
|
||||
auto currentTime = std::chrono::system_clock::to_time_t(now);
|
||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 100;
|
||||
std::tm* localTime = std::localtime(¤tTime);
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(localTime, "%H-%M-%S") << "-" << std::setfill('0') << std::setw(2) << ms.count();
|
||||
return ss.str();
|
||||
}
|
||||
static QString getCurrentDate()
|
||||
{
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
return currentDateTime.toString("yyyy-MM-dd");
|
||||
}
|
||||
static QString getCurrentHour()
|
||||
{
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
return QString::number(currentDateTime.time().hour()) + "H";
|
||||
}
|
||||
inline std::string utf8_to_gbk(const std::string& str)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring tmp_wstr = conv.from_bytes(str);
|
||||
//GBK locale name in windows
|
||||
const char* GBK_LOCALE_NAME = ".936";
|
||||
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
|
||||
return convert.to_bytes(tmp_wstr);
|
||||
}
|
||||
QString getOriSaveFromat()
|
||||
{
|
||||
return oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"
|
||||
+ "ORI_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".bmp";
|
||||
}
|
||||
QString getResSaveFromat()
|
||||
{
|
||||
return resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"
|
||||
+ "RES_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".png";
|
||||
}
|
||||
QString byteArrayToUnicode(const QByteArray array) {
|
||||
|
||||
// state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功
|
||||
// 如果转换成功,则值为0,如果值大于0,则说明转换失败
|
||||
QTextCodec::ConverterState state;
|
||||
// 先尝试使用utf-8的方式把QByteArray转换成QString
|
||||
QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state);
|
||||
// 如果转换时无效字符数量大于0,说明编码格式不对
|
||||
if (state.invalidChars > 0)
|
||||
{
|
||||
// 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了)
|
||||
text = QTextCodec::codecForName("GBK")->toUnicode(array);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
// 获取当前时间点
|
||||
auto now = std::chrono::system_clock::now();
|
||||
|
||||
// 转换为字符串
|
||||
auto currentTime = std::chrono::system_clock::to_time_t(now);
|
||||
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()) % 100;
|
||||
std::tm* localTime = std::localtime(¤tTime);
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(localTime, "%H-%M-%S") << "-" << std::setfill('0') << std::setw(2) << ms.count();
|
||||
return ss.str();
|
||||
}
|
||||
static QString getCurrentDate()
|
||||
{
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
return currentDateTime.toString("yyyy-MM-dd");
|
||||
}
|
||||
static QString getCurrentHour()
|
||||
{
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
return QString::number(currentDateTime.time().hour()) + "H";
|
||||
}
|
||||
QString byteArrayToUnicode(const QByteArray array) {
|
||||
|
||||
// state用于保存转换状态,它的成员invalidChars,可用来判断是否转换成功
|
||||
// 如果转换成功,则值为0,如果值大于0,则说明转换失败
|
||||
QTextCodec::ConverterState state;
|
||||
// 先尝试使用utf-8的方式把QByteArray转换成QString
|
||||
QString text = QTextCodec::codecForName("UTF-8")->toUnicode(array.constData(), array.size(), &state);
|
||||
// 如果转换时无效字符数量大于0,说明编码格式不对
|
||||
if (state.invalidChars > 0)
|
||||
{
|
||||
// 再尝试使用GBK的方式进行转换,一般就能转换正确(当然也可能是其它格式,但比较少见了)
|
||||
text = QTextCodec::codecForName("GBK")->toUnicode(array);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
static cv::Rect findMaxAreaContour(cv::Mat src)
|
||||
{
|
||||
int maxIndex = 0, maxArea = 0;
|
||||
std::vector<std::vector<cv::Point>>contours;
|
||||
cv::findContours(src, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
|
||||
if (contours.size() == 0)
|
||||
return cv::Rect(0, 0, 0, 0);
|
||||
for (int i = 0; i < contours.size(); i++)
|
||||
{
|
||||
int Area = cv::contourArea(contours[i]);
|
||||
if (Area > maxArea)
|
||||
{
|
||||
maxArea = Area;
|
||||
maxIndex = i;
|
||||
}
|
||||
}
|
||||
if (contours.size() != 0)
|
||||
return cv::boundingRect(contours[maxIndex]);
|
||||
return cv::Rect(0, 0, 0, 0);
|
||||
}
|
||||
inline std::string utf8_to_gbk(const std::string& str)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring tmp_wstr = conv.from_bytes(str);
|
||||
//GBK locale name in windows
|
||||
const char* GBK_LOCALE_NAME = ".936";
|
||||
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
|
||||
return convert.to_bytes(tmp_wstr);
|
||||
}
|
||||
void getAllFiles(std::string path, std::vector<std::string>& files, std::string format)
|
||||
{
|
||||
intptr_t hFile = 0;//文件句柄
|
||||
struct _finddata_t fileinfo;//文件信息
|
||||
std::string p;
|
||||
if ((hFile = _findfirst(p.assign(path).append("\\*" + format).c_str(), &fileinfo)) != -1) //文件存在
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((fileinfo.attrib & _A_SUBDIR))//判断是否为文件夹
|
||||
{
|
||||
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)//文件夹名中不含"."和".."
|
||||
{
|
||||
files.push_back(p.assign(path).append("\\").append(fileinfo.name)); //保存文件夹名
|
||||
getAllFiles(p.assign(path).append("\\").append(fileinfo.name), files, format); //递归遍历文件夹
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
files.push_back(p.assign(path).append("\\").append(fileinfo.name));//如果不是文件夹,储存文件名
|
||||
}
|
||||
} while (_findnext(hFile, &fileinfo) == 0);
|
||||
_findclose(hFile);
|
||||
}
|
||||
}
|
||||
QString getOriSaveFormat(QString SN)
|
||||
{
|
||||
QString path = oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + SN + "//";
|
||||
createDirectoryIfNotExists(path);
|
||||
return path + "ORI_" + cameraKey_index + "_" + SN + "_" + QString::fromStdString(getCurrentTime()) + ".bmp";
|
||||
}
|
||||
QString getResSaveFromat(QString SN)
|
||||
{
|
||||
QString path = resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + SN + "//";
|
||||
createDirectoryIfNotExists(path);
|
||||
return path + "RES_" + cameraKey_index + "_" + SN + "_" + QString::fromStdString(getCurrentTime()) + ".png";
|
||||
}
|
||||
// 缺陷信息结构体
|
||||
typedef struct {
|
||||
QString defectName = "";//缺陷名称
|
||||
@@ -232,6 +280,8 @@ void GetStringSize(HDC hdc, const char* str, int* w, int* h)
|
||||
if (h != 0) *h = size.cy;
|
||||
}
|
||||
//在图像写中文,英文也可以写
|
||||
|
||||
|
||||
void putTextZH(cv::Mat& dst, const char* str, cv::Point org, cv::Scalar color, int fontsize,
|
||||
const char* fn = "Arial", bool italic = false, bool underline = false)
|
||||
{
|
||||
@@ -397,7 +447,7 @@ void drawDefects(cv::Mat& sourceMat, QQueue<defectInfo> defectInfoList)
|
||||
|
||||
|
||||
//判断文件夹是否存在,不存在则创建
|
||||
void Hd_AI_algo_jixing1::isDirExist(QString fullDirName)
|
||||
void Hd_AI_algo_jiXing_L::isDirExist(QString fullDirName)
|
||||
{
|
||||
QDir* photo = new QDir;
|
||||
bool exist = photo->exists(fullDirName);
|
||||
@@ -415,28 +465,27 @@ void Hd_AI_algo_jixing1::isDirExist(QString fullDirName)
|
||||
photo = nullptr;
|
||||
}
|
||||
|
||||
Hd_AI_algo_jixing1* create()
|
||||
Hd_AI_algo_jiXing_L* create()
|
||||
{
|
||||
qDebug() << "[INFO] " << " Hd_AI_algo_jixing1 create success!" ;
|
||||
return new Hd_AI_algo_jixing1;
|
||||
qDebug() << "[INFO] " << " Hd_AI_algo_jiXing_L create success!";
|
||||
return new Hd_AI_algo_jiXing_L;
|
||||
}
|
||||
|
||||
void destory(Hd_AI_algo_jixing1* ptr)
|
||||
void destory(Hd_AI_algo_jiXing_L* ptr)
|
||||
{
|
||||
qDebug() << "[INFO] " << "Hd_AI_algo_jixing1 destory success!";
|
||||
if(ptr)
|
||||
qDebug() << "[INFO] " << "Hd_AI_algo_jiXing_L destory success!";
|
||||
if (ptr)
|
||||
{
|
||||
delete ptr;
|
||||
ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Hd_AI_algo_jixing1::Hd_AI_algo_jixing1()
|
||||
Hd_AI_algo_jiXing_L::Hd_AI_algo_jiXing_L()
|
||||
{
|
||||
detect_mutex = new QMutex;
|
||||
saveStruct_mutex = new QMutex;
|
||||
ifdetectThread = false;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
QString DirPath = "E:/testImg/source" + QString::number(i);
|
||||
@@ -456,7 +505,7 @@ Hd_AI_algo_jixing1::Hd_AI_algo_jixing1()
|
||||
}
|
||||
}
|
||||
|
||||
Hd_AI_algo_jixing1::~Hd_AI_algo_jixing1()
|
||||
Hd_AI_algo_jiXing_L::~Hd_AI_algo_jiXing_L()
|
||||
{
|
||||
ifdetectThread = false;
|
||||
Sleep(10);
|
||||
@@ -470,70 +519,76 @@ Hd_AI_algo_jixing1::~Hd_AI_algo_jixing1()
|
||||
delete saveStruct_mutex;
|
||||
saveStruct_mutex = nullptr;
|
||||
}
|
||||
|
||||
/*DestroySegObj(pSeg);
|
||||
DestroyClsObj(pCls);*/
|
||||
}
|
||||
//从类中读数据到实例对象
|
||||
bool Hd_AI_algo_jixing1::readData(std::vector<cv::Mat>&vec_mat,QByteArray &data)
|
||||
bool Hd_AI_algo_jiXing_L::readData(std::vector<cv::Mat>& vec_mat, QByteArray& data)
|
||||
{
|
||||
detect_mutex->lock();
|
||||
//qDebug() << __FUNCTION__ << " line:" <<__LINE__ << " data len:" << data.length();
|
||||
if (resMat.size()>0)
|
||||
if (resMat.size() > 0)
|
||||
{
|
||||
vec_mat.push_back(resMat[0]);
|
||||
resMat.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(HikMat.size()>0)
|
||||
if (HikMat.size() > 0)
|
||||
vec_mat.push_back(HikMat[0]);
|
||||
//qDebug() << __FUNCTION__ << " line:" << __LINE__ << " resMat.data err:";
|
||||
}
|
||||
//if (allNum++ % 2 == 0)
|
||||
// data = "2*3*2";// resByte.dequeue();
|
||||
//else
|
||||
data = QByteArray::number(algoResult) + "&" + QByteArray::number(algoResult - 1) + "+" + QByteArray::number(algoResult);
|
||||
//QByteArray resultCmd = resultCmdSplitStart +
|
||||
// resultPlc
|
||||
// + resultCmdSplitEnd;
|
||||
resByte.clear();
|
||||
QVariant jiXingJieGuo = (resultPlc == "1") ? "OK" : "NG";
|
||||
data = logicUiTransport::encodeAllData(SN,{ resultPlc }, { {"极性检测结果",jiXingJieGuo}});
|
||||
////之后根据结果类修改
|
||||
//if(resIfNg == true)
|
||||
// data = "NG";
|
||||
//else data = "OK";
|
||||
detect_mutex->unlock();
|
||||
/*if(cameraKey_index.contains('_'))
|
||||
qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName:"
|
||||
qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName:"
|
||||
<< cameraKey_index.split("_")[0] << " imgIndex:" << cameraKey_index.split("_")[1];
|
||||
else
|
||||
qDebug() << "[INFO] " << __FUNCTION__ << " line:" << __LINE__ << " checkImg getDetectData--CameraName imgIndex:" << cameraKey_index;*/
|
||||
return true;
|
||||
}
|
||||
//从类中读数据到实例对象
|
||||
bool Hd_AI_algo_jixing1::encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte)
|
||||
bool Hd_AI_algo_jiXing_L::encodeResultValue(QVector<std::string> append_value, QByteArray& resultByte)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string sendMsg;
|
||||
for(int i = 0 ; i < append_value.size();i++)
|
||||
for (int i = 0; i < append_value.size(); i++)
|
||||
{
|
||||
std::string value = append_value.at(1);
|
||||
//type
|
||||
int type = 3;
|
||||
std::string m_type;
|
||||
m_type.insert(0,4,'1');
|
||||
memcpy ( (void*)m_type.c_str(),(void*)&type,4 );
|
||||
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 );
|
||||
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);
|
||||
} catch (QString ev)
|
||||
}
|
||||
catch (QString ev)
|
||||
{
|
||||
qCritical() << "[Error] " << " ev:" << ev;
|
||||
return false;
|
||||
@@ -541,13 +596,14 @@ bool Hd_AI_algo_jixing1::encodeResultValue(QVector<std::string> append_value,QBy
|
||||
return true;
|
||||
}
|
||||
|
||||
int myallNum[4] = {0};
|
||||
int myallNum[4] = { 0 };
|
||||
QMap<int, cv::Mat> lastImgMap;
|
||||
//接收数据
|
||||
bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &data)
|
||||
bool Hd_AI_algo_jiXing_L::writeData(std::vector<cv::Mat>& vec_mat, QByteArray& data)
|
||||
{
|
||||
//qDebug() << __FUNCTION__ << "line:"<< __LINE__ << " data len" << data.length() ;
|
||||
if(vec_mat.empty())
|
||||
|
||||
if (vec_mat.empty())
|
||||
{
|
||||
qCritical() << "[Error] " << " vec_mat is null !";
|
||||
return false;
|
||||
@@ -555,7 +611,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
detect_mutex->lock();
|
||||
HikMat.clear();
|
||||
for (int i = 0; i < vec_mat.size(); i++)
|
||||
HikMat.enqueue(vec_mat[i]);
|
||||
HikMat.enqueue(vec_mat[i]);
|
||||
|
||||
QByteArray source_savePath;
|
||||
QByteArray sData = data;
|
||||
@@ -566,8 +622,9 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
cameraKey_index = splitDataList[2];
|
||||
QByteArray saveDir = splitDataList[0] + "/" + splitDataList[1] + "/";
|
||||
isDirExist(byteArrayToUnicode(saveDir)); //不存在,创建
|
||||
QString sdataTime= QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||||
QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||||
source_savePath = splitDataList[0] + "/" + splitDataList[1] + "/" + sdataTime.toLocal8Bit() + "-" + splitDataList[2] + "-" + splitDataList[3];// +".bmp";
|
||||
SN = splitDataList[3];
|
||||
}
|
||||
//int index = -1;
|
||||
/*if (sData.contains("offline-camera0"))
|
||||
@@ -592,10 +649,8 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//");
|
||||
addImgToSaveStruct(HikMat[0], "0", getOriSaveFromat());//保存原图
|
||||
|
||||
addImgToSaveStruct(HikMat[0], "0", getOriSaveFormat(SN));//保存原图
|
||||
//if (!source_savePath.isEmpty())
|
||||
//{
|
||||
// //std::cout << "try savePath::" << savePath.toStdString() << std::endl;
|
||||
@@ -646,7 +701,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
|
||||
/*saveKey.enqueue("datalist[0]");
|
||||
Dir2D.enqueue("datalist[1]");
|
||||
QStringList SN_dataTime;
|
||||
QStringList SN_dataTime;
|
||||
SN_dataTime = datalist[3].split('_');
|
||||
DateTime1 = "SN_dataTime[1]";
|
||||
SN.enqueue("SN_dataTime[0]");*/
|
||||
@@ -663,7 +718,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
|
||||
//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1...
|
||||
//初始化
|
||||
bool Hd_AI_algo_jixing1::initParas(QByteArray& byte)
|
||||
bool Hd_AI_algo_jiXing_L::initParas(QByteArray& byte)
|
||||
{
|
||||
initValueList = byte.split('+');
|
||||
QStringList valueiList;
|
||||
@@ -688,13 +743,11 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte)
|
||||
valueiList.append(valuei);
|
||||
}
|
||||
|
||||
|
||||
/*pSeg = CreateSegObjS(pSeg_modulePath, 128, gpuId);
|
||||
pCls = CreateClsObjV3(pCls_modulePath, gpuId, 1);*/
|
||||
|
||||
|
||||
//StationNo = vec_ret.at(0).toInt();
|
||||
|
||||
//InitThreads(StationNo, img2D);
|
||||
//InitModels(StationNo, img2D);
|
||||
|
||||
@@ -703,9 +756,9 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte)
|
||||
|
||||
//线程检测:结果类完成时,使用
|
||||
//ifThreadRunDetect = true;
|
||||
//QFuture<void> future1 = QtConcurrent::run(this, &Hd_AI_algo_jixing1::detectThread);
|
||||
//QFuture<void> future1 = QtConcurrent::run(this, &Hd_AI_algo_jiXing_L::detectThread);
|
||||
//运行存图线程
|
||||
QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_algo_jixing1::saveImgThread);
|
||||
QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_algo_jiXing_L::saveImgThread);
|
||||
//detectThread();
|
||||
|
||||
//原图总文件夹
|
||||
@@ -715,51 +768,52 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte)
|
||||
//结果图总文件夹
|
||||
isDirExist(resImgSaveDir);
|
||||
|
||||
myEngine.SetProcedurePath("./halconFilesAlgo/AlgoLibrary_628_1.hdpl"); //设置hdvp路径
|
||||
//qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ;
|
||||
myEngine.SetProcedurePath("./halconFilesAlgo/JX_ColorInspection.hdpl"); //设置hdvp路径
|
||||
return true;
|
||||
}
|
||||
// 解码
|
||||
bool Hd_AI_algo_jixing1::decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret)
|
||||
bool Hd_AI_algo_jiXing_L::decodeAiValue(QByteArray byte, QVector<QByteArray>& vec_ret)
|
||||
{
|
||||
if(byte.isEmpty())
|
||||
if (byte.isEmpty())
|
||||
{
|
||||
qCritical() << "[Error] " << " byte is null!";
|
||||
return false;
|
||||
}
|
||||
|
||||
/*******************************************/
|
||||
byte.remove(0,8);
|
||||
QByteArray mm_data = byte.mid(0,4);
|
||||
memcpy((void*)¶mNum,(void*)mm_data.data(), 4);
|
||||
byte.remove(0, 8);
|
||||
QByteArray mm_data = byte.mid(0, 4);
|
||||
memcpy((void*)¶mNum, (void*)mm_data.data(), 4);
|
||||
qDebug() << "[INFO] " << " paramNum:" << paramNum;
|
||||
byte.remove(0,4);
|
||||
byte.remove(0, 4);
|
||||
/*******************************************/
|
||||
|
||||
while (!byte.isEmpty())
|
||||
{
|
||||
int type = 0;
|
||||
QByteArray m_type = byte.mid(0,4);
|
||||
memcpy((void*)&type,(void*)m_type.data(), 4);
|
||||
byte.remove(0,4);
|
||||
QByteArray m_type = byte.mid(0, 4);
|
||||
memcpy((void*)&type, (void*)m_type.data(), 4);
|
||||
byte.remove(0, 4);
|
||||
|
||||
int len = 0;
|
||||
QByteArray m_len = byte.mid(0,4);
|
||||
memcpy((void*)&len,(void*)m_len.data(), 4);
|
||||
byte.remove(0,4);
|
||||
QByteArray m_len = byte.mid(0, 4);
|
||||
memcpy((void*)&len, (void*)m_len.data(), 4);
|
||||
byte.remove(0, 4);
|
||||
|
||||
QByteArray mm_data = byte.mid(0,len);
|
||||
QByteArray mm_data = byte.mid(0, len);
|
||||
vec_ret.append(mm_data);
|
||||
byte.remove(0,len);
|
||||
byte.remove(0, len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------检测流程,根据实际项目修改---------
|
||||
bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime)
|
||||
bool Hd_AI_algo_jiXing_L::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
//存图数据加保存队列,加锁,避免数据访问冲突
|
||||
saveStruct_mutex->lock();
|
||||
saveImgStruct mySave;
|
||||
@@ -774,7 +828,7 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
QJsonObject obj;
|
||||
obj.insert("result_key", "mysaveKey");
|
||||
obj.insert("SN", "mySN");
|
||||
obj.insert("DataTime", "myDataTime");
|
||||
obj.insert("DataTime", "myDa taTime");
|
||||
|
||||
|
||||
//QFile csvName("test.csv");
|
||||
@@ -786,68 +840,84 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
// csvName.write(lines[i].toStdString().c_str());
|
||||
// csvName.close();
|
||||
//}
|
||||
HDevEngineCpp::HDevProcedure proc("YH_Color_Inspection");
|
||||
HDevProcedureCall procedureCall(proc);
|
||||
QQueue<defectInfo> defectInfoList;
|
||||
|
||||
//sourceImg = cv::imread("D:\\mySN15-46-33-86.bmp",-1);
|
||||
//sourceImg = cv::imread("F:/CCD/TEST/20241024-091531.bmp", -1);
|
||||
cv::Mat Paint;
|
||||
sourceImg.copyTo(Paint);
|
||||
//极性检测
|
||||
if (Paint.channels() == 1)
|
||||
cvtColor(Paint, Paint, COLOR_GRAY2BGR);
|
||||
|
||||
|
||||
HDevEngineCpp::HDevProcedure proc("JX_Inspection");
|
||||
HDevProcedureCall procedureCall(proc);
|
||||
|
||||
HObject in_Image;
|
||||
HTuple out_ColorType;
|
||||
HTuple out_Flag;
|
||||
HTuple out_Flag, out_ColorType;
|
||||
MatToHObject(sourceImg, &in_Image);
|
||||
procedureCall.SetInputIconicParamObject("in_Image", in_Image);//设置输入图像类变量
|
||||
|
||||
procedureCall.SetInputIconicParamObject("in_Image", in_Image);//
|
||||
procedureCall.Execute();//执行halcon程序
|
||||
out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出图像类变量
|
||||
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
|
||||
//相机1 OK为铝 NG为铜s
|
||||
|
||||
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出图像类变量
|
||||
out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出控制类变量
|
||||
resultPlc = "1";
|
||||
if (out_Flag.D() == 1)
|
||||
{
|
||||
if (out_ColorType.D() == 2)//铝
|
||||
int res1 = out_ColorType[0].D();
|
||||
int res2 = out_ColorType[1].D();
|
||||
//1铜 2铝+
|
||||
switch (res1)
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("铝极").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300);
|
||||
//cv::putText(sourceImg, "Aluminium", cv::Point(0, 240), 2, 10, cv::Scalar(0, 255, 0), 10);
|
||||
cv::putText(Paint, "OK", cv::Point(0, 550), 2, 10, cv::Scalar(0, 255, 0), 10);
|
||||
algoResult = 1;
|
||||
//Result = 1 ? 2;
|
||||
//Result = 1;
|
||||
case 0:
|
||||
putTextHusky(Paint, utf8_to_gbk("异常").c_str(), cv::Point(0, 0), cv::Scalar(0, 0, 255), 300);
|
||||
break;
|
||||
case 1:
|
||||
putTextHusky(Paint, utf8_to_gbk("铜").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 500);
|
||||
break;
|
||||
case 2:
|
||||
putTextHusky(Paint, utf8_to_gbk("铝").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 500);
|
||||
break;
|
||||
}
|
||||
else if (out_ColorType.D() == 1)//铜
|
||||
|
||||
switch (res2)
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("铜极").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300);
|
||||
//cv::putText(sourceImg, "Copper", cv::Point(0, 240), 2, 10, cv::Scalar(0, 255, 0), 10);
|
||||
cv::putText(Paint, "NG", cv::Point(0, 550), 2, 10, cv::Scalar(0, 0,255), 10);
|
||||
algoResult = 1;
|
||||
case 0:
|
||||
putTextHusky(Paint, utf8_to_gbk("异常").c_str(), cv::Point(0, Paint.rows - 500), cv::Scalar(0, 0, 255), 300);
|
||||
break;
|
||||
case 1:
|
||||
putTextHusky(Paint, utf8_to_gbk("铜").c_str(), cv::Point(0, Paint.rows - 500), cv::Scalar(0, 255, 0), 500);
|
||||
break;
|
||||
case 2:
|
||||
putTextHusky(Paint, utf8_to_gbk("铝").c_str(), cv::Point(0, Paint.rows - 500), cv::Scalar(0, 255, 0), 500);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
//T 为铜OK,L为铝OK
|
||||
if (res1 == 2 && res2 == 2)//铝ok
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("OK").c_str(), cv::Point(Paint.cols - 800, 0), cv::Scalar(0, 255, 0), 500);
|
||||
}
|
||||
else
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300);
|
||||
// cv::putText(sourceImg, "Algo error1", cv::Point(0, 240), 2, 10, cv::Scalar(0, 0, 255), 10);
|
||||
//Result = 2;
|
||||
putTextHusky(Paint, utf8_to_gbk("NG").c_str(), cv::Point(Paint.cols - 800, 0), cv::Scalar(0, 0, 255), 500);
|
||||
resultPlc = "1";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300);
|
||||
// cv::putText(sourceImg, "Algo error2", cv::Point(0, 240), 2, 10, cv::Scalar(0, 0, 255), 10);
|
||||
}
|
||||
putTextHusky(Paint, utf8_to_gbk("NG1").c_str(), cv::Point(0, 50), cv::Scalar(0, 0, 255), 500);
|
||||
|
||||
|
||||
QQueue<defectInfo> defectInfoList;
|
||||
|
||||
/*ho_Image.Clear();
|
||||
hv_out_Value.Clear();
|
||||
hv_Make.Clear();*/
|
||||
|
||||
detect_mutex->lock();
|
||||
//resMat = sourceImg.clone();
|
||||
//sourceImg.copyTo(resMat);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
resMat.push_back(Paint);
|
||||
//结果图画框和缺陷,在resMat上绘制
|
||||
if (resMat.size() > 0)
|
||||
drawDefects(resMat[0], defectInfoList);
|
||||
|
||||
//QByteArray,根据实际项目进行解析
|
||||
//参数,例:返回结果图;相机关键字(SN或userID)+保存路径+缺陷信息列表(缺陷名称,缺陷位置int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷面积double)
|
||||
|
||||
QJsonArray detaillists;
|
||||
//QByteArrayList resQbyte;
|
||||
for (int i = 0; i < defectInfoList.size(); i++)
|
||||
@@ -872,7 +942,7 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1]));
|
||||
detailObj.insert("defectScalar2", QString::number(mdefect.defectScalar[2]));
|
||||
detailObj.insert("defectArea", QString::number(mdefect.defectArea));
|
||||
detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width* mdefect.defectRect.width+ mdefect.defectRect.height* mdefect.defectRect.height)));
|
||||
detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width * mdefect.defectRect.width + mdefect.defectRect.height * mdefect.defectRect.height)));
|
||||
|
||||
detaillists.append(detailObj);
|
||||
}
|
||||
@@ -885,14 +955,13 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
//emit sendResultData(resMat, resQbyte);
|
||||
//resQbyte.clear();
|
||||
|
||||
isDirExist(resImgSaveDir + mysaveKey1 + "/");
|
||||
//isDirExist(resImgSaveDir + mysaveKey1 + "/");
|
||||
QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png";
|
||||
//存图数据入队,按需
|
||||
QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||||
if (resMat.size() > 0)
|
||||
{
|
||||
createDirectoryIfNotExists(resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//");
|
||||
addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//保存原图
|
||||
addImgToSaveStruct(resMat[0], "0", getResSaveFromat(SN));//保存原图
|
||||
}
|
||||
detect_mutex->unlock();
|
||||
|
||||
@@ -936,7 +1005,7 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
}
|
||||
|
||||
//存图加入队列
|
||||
void Hd_AI_algo_jixing1::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath)
|
||||
void Hd_AI_algo_jiXing_L::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath)
|
||||
{
|
||||
//存图数据加保存队列,加锁,避免数据访问冲突
|
||||
saveStruct_mutex->lock();
|
||||
@@ -948,7 +1017,7 @@ void Hd_AI_algo_jixing1::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QS
|
||||
saveStruct.enqueue(mySave);
|
||||
saveStruct_mutex->unlock();
|
||||
}
|
||||
void Hd_AI_algo_jixing1::saveImgThread()
|
||||
void Hd_AI_algo_jiXing_L::saveImgThread()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
@@ -964,7 +1033,7 @@ void Hd_AI_algo_jixing1::saveImgThread()
|
||||
saveImgStruct mysaveStruct = saveStruct.dequeue();
|
||||
saveStruct_mutex->unlock();
|
||||
stop = clock();
|
||||
if(stop-start >1000)
|
||||
if (stop - start > 1000)
|
||||
std::cout << "lock stop-start >1000::************************" << stop - start << std::endl;
|
||||
start = clock();
|
||||
if (mysaveStruct.out_Mat.data)
|
||||
@@ -972,17 +1041,17 @@ void Hd_AI_algo_jixing1::saveImgThread()
|
||||
//std::cout << "savePath::" << mysaveStruct.savePath << std::endl;
|
||||
stop = clock();
|
||||
if (stop - start > 1000)
|
||||
std::cout << "imwrite stop-start >1000::--------------------------"<< stop - start << std::endl;
|
||||
std::cout << "imwrite stop-start >1000::--------------------------" << stop - start << std::endl;
|
||||
_sleep(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
//检测线程,应当只运行一次
|
||||
void Hd_AI_algo_jixing1::detectThread()
|
||||
void Hd_AI_algo_jiXing_L::detectThread()
|
||||
{
|
||||
do
|
||||
{
|
||||
if (!ifdetectThread)return;
|
||||
if (!ifdetectThread)return;
|
||||
|
||||
//此两行代码,避免程序卡死;_sleep的时间根据实际项目调整
|
||||
_sleep(2);
|
||||
@@ -1012,9 +1081,9 @@ void Hd_AI_algo_jixing1::detectThread()
|
||||
isDirExist(resImgSaveDir + mysaveKey);
|
||||
|
||||
}
|
||||
|
||||
|
||||
//测试相机的,
|
||||
//while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5);
|
||||
// while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5);
|
||||
|
||||
//存图数据入队
|
||||
//addImgToSaveStruct(sourceImg1, mysaveKey, oriImgSaveDir + mysaveKey + "/" + mySN + myDataTime + ".bmp");
|
||||
@@ -1027,14 +1096,14 @@ void Hd_AI_algo_jixing1::detectThread()
|
||||
myDir2D.clear();
|
||||
mySN.clear();
|
||||
myDataTime.clear();
|
||||
qApp->processEvents();
|
||||
qApp->processEvents();
|
||||
|
||||
} while (ifThreadRunDetect);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static int runNum = 0;
|
||||
bool Hd_AI_algo_jixing1::run()
|
||||
bool Hd_AI_algo_jiXing_L::run()
|
||||
{
|
||||
clock_t start, stop;
|
||||
start = clock();
|
||||
@@ -1042,14 +1111,14 @@ bool Hd_AI_algo_jixing1::run()
|
||||
//Sleep(1000);
|
||||
detectThread();
|
||||
stop = clock();
|
||||
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++<<" cutTime::"<<stop-start;
|
||||
qDebug() << __FUNCTION__ << "line:" << __LINE__ << " run start ::runNum::" << runNum++ << " cutTime::" << stop - start;
|
||||
|
||||
|
||||
|
||||
//qDebug() << __FUNCTION__ << "line:" << __LINE__ << "[INFO] " << "Mat_name: " << Mat_name << " run end";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Hd_AI_algo_jixing1::checkStatus()
|
||||
bool Hd_AI_algo_jiXing_L::checkStatus()
|
||||
{
|
||||
status = moduleStatus;
|
||||
return status;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef Hd_AI_algo_jixing1_H
|
||||
#define Hd_AI_algo_jixing1_H
|
||||
#ifndef Hd_AI_algo_jiXing_L_H
|
||||
#define Hd_AI_algo_jiXing_L_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <atlstr.h>
|
||||
@@ -15,18 +15,16 @@
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <halconcpp/HalconCpp.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "imgproc/imgproc_c.h"
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
#include <HDevEngineCpp.h>
|
||||
|
||||
using namespace HDevEngineCpp;
|
||||
|
||||
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct;
|
||||
//{
|
||||
@@ -35,16 +33,16 @@ struct saveImgStruct;
|
||||
// std::string savePath; //保存路径
|
||||
//};
|
||||
|
||||
//初始化流程(一次):Hd_AI_algo_jixing1,initParas
|
||||
//初始化流程(一次):Hd_AI_algo_jiXing_L,initParas
|
||||
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
|
||||
class Hd_AI_algo_jixing1 :public Base
|
||||
class Hd_AI_algo_jiXing_L :public Base
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Hd_AI_algo_jixing1();
|
||||
virtual ~Hd_AI_algo_jixing1();
|
||||
Hd_AI_algo_jiXing_L();
|
||||
virtual ~Hd_AI_algo_jiXing_L();
|
||||
//从类中读数据到实例对象
|
||||
bool readData(std::vector<cv::Mat>&,QByteArray&);
|
||||
bool readData(std::vector<cv::Mat>&, QByteArray&);
|
||||
//实例对象把数据写入到类
|
||||
bool writeData(std::vector<cv::Mat>&, QByteArray&);
|
||||
bool initParas(QByteArray&);
|
||||
@@ -53,17 +51,15 @@ public:
|
||||
//线程状态
|
||||
bool checkStatus();// { return true; };
|
||||
|
||||
bool encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte);
|
||||
bool decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret);
|
||||
bool encodeResultValue(QVector<std::string> append_value, QByteArray& resultByte);
|
||||
bool decodeAiValue(QByteArray byte, QVector<QByteArray>& vec_ret);
|
||||
//---------检测流程,根据实际项目修改---------
|
||||
bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
HDevEngine myEngine;
|
||||
int allNum = 0;
|
||||
int StationNo=0;
|
||||
int StationNo = 0;
|
||||
int img2D = 2;
|
||||
|
||||
bool moduleStatus = true;
|
||||
@@ -71,13 +67,13 @@ private:
|
||||
//输入图片队列
|
||||
QQueue<cv::Mat> HikMat;
|
||||
//输入关键字队列
|
||||
QString saveKey="saveKey";
|
||||
QString saveKey = "saveKey";
|
||||
//结果路径文件夹队列
|
||||
QString Dir2D="Dir2D";
|
||||
QString Dir2D = "Dir2D";
|
||||
//产品SN队列
|
||||
QString SN="SN";
|
||||
QString SN = "SN";
|
||||
//产品时间戳队列
|
||||
QString DateTime1="DateTime1";
|
||||
QString DateTime1 = "DateTime1";
|
||||
|
||||
int paramNum;
|
||||
|
||||
@@ -94,7 +90,7 @@ private:
|
||||
void detectThread();
|
||||
//存图线程
|
||||
void saveImgThread();
|
||||
|
||||
|
||||
//保存图片队列
|
||||
QQueue<saveImgStruct> saveStruct;
|
||||
|
||||
@@ -107,8 +103,8 @@ private:
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Q_DECL_EXPORT Hd_AI_algo_jixing1 * create();
|
||||
Q_DECL_EXPORT void destory(Hd_AI_algo_jixing1 * ptr);
|
||||
Q_DECL_EXPORT Hd_AI_algo_jiXing_L* create();
|
||||
Q_DECL_EXPORT void destory(Hd_AI_algo_jiXing_L* ptr);
|
||||
}
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct
|
||||
|
||||
@@ -3,7 +3,7 @@ get_filename_component(CURRENT_FOLDER ${CMAKE_CURRENT_SOURCE_DIR} NAME)
|
||||
string(TIMESTAMP RUN_TIME)
|
||||
message( " model start : " ${CURRENT_FOLDER}:${RUN_TIME})
|
||||
|
||||
set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" )
|
||||
set(DLL_NAMES "opencv" "halcon" "halconAlgo" "myTools" "handdleAI")
|
||||
foreach(child ${DLL_NAMES})
|
||||
LIST(APPEND ENV_INCLUDE ${${child}_include})
|
||||
LIST(APPEND ENV_LIB ${${child}_lib})
|
||||
@@ -39,7 +39,7 @@ FILE(GLOB UI_FILES "./*.ui")
|
||||
#find_package(Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
|
||||
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS network REQUIRED)
|
||||
add_library(${CURRENT_FOLDER} SHARED
|
||||
${HEAD_FILES}
|
||||
${SRC_FILES}
|
||||
@@ -58,6 +58,7 @@ set_target_properties(${CURRENT_FOLDER} PROPERTIES LINKER_LANGUAGE C
|
||||
target_link_libraries(${CURRENT_FOLDER} PRIVATE
|
||||
${ENV_TARGET}
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Network
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
#include "Hd_AI_algo_jixing_T.h"
|
||||
#include "Hd_AI_algo_jiXing_T.h"
|
||||
#include <QDateTime>
|
||||
#include <codecvt>
|
||||
|
||||
#include <QtConcurrent/QtConcurrent>
|
||||
#include <qfuture.h>
|
||||
#include <QTextCodec>
|
||||
#include <filesystem>
|
||||
#include <myTools.h>
|
||||
#include <algo.h>
|
||||
#include <corecrt_wstring.h>
|
||||
#include <codecvt>
|
||||
#include <myTools.h>
|
||||
#include <global.h>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
//原图保存文件夹
|
||||
QString oriImgSaveDir = "D:/D601线/超声波预焊机/极性检测CCD/原图/";
|
||||
QByteArray resultPlc;
|
||||
//原图保存文件夹s
|
||||
QString oriImgSaveDir = "D:/601线/终焊CCD/极性检测CCD/原图/";
|
||||
//原图class图保存文件夹
|
||||
QString classImgSaveDir = "D:/D601线/超声波预焊机/极性检测CCD/class图/";
|
||||
QString classImgSaveDir = "D:/601线/终焊CCD/极性检测CCD/class图/";
|
||||
//结果保存文件夹
|
||||
QString resImgSaveDir = "D:/D601线/超声波预焊机/极性检测CCD/结果图/";
|
||||
|
||||
QString resImgSaveDir = "D:/601线/终焊CCD/极性检测CCD/结果图/";
|
||||
int algoResult = 0;//0 OK 1 NG
|
||||
//切图的class的width,根据项目实际设置!
|
||||
int sizeW = 150;
|
||||
//切图的class的height,根据项目实际设置!
|
||||
int sizeH = 150;
|
||||
//切图的class的width,根据项目实际设置!0为黑,255为白;
|
||||
int fillColour = 0;
|
||||
int algoResult;
|
||||
|
||||
|
||||
//检测线程锁
|
||||
QMutex* detect_mutex;
|
||||
//保存线程锁
|
||||
//保存线程锁
|
||||
QMutex* saveStruct_mutex;
|
||||
//检测线程运行标志
|
||||
bool ifdetectThread = false;
|
||||
@@ -36,6 +37,7 @@ int algoResult;
|
||||
|
||||
//初始化参数列表
|
||||
QByteArrayList initValueList;
|
||||
|
||||
static void createDirectoryIfNotExists(const QString& path) {
|
||||
QDir dir;
|
||||
dir.mkpath(path);
|
||||
@@ -61,16 +63,7 @@ int algoResult;
|
||||
static QString getCurrentHour()
|
||||
{
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
return QString::number(currentDateTime.time().hour()) + "H";
|
||||
}
|
||||
inline std::string utf8_to_gbk(const std::string& str)
|
||||
{
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring tmp_wstr = conv.from_bytes(str);
|
||||
//GBK locale name in windows
|
||||
const char* GBK_LOCALE_NAME = ".936";
|
||||
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
|
||||
return convert.to_bytes(tmp_wstr);
|
||||
return QString::number(currentDateTime.time().hour())+"H";
|
||||
}
|
||||
QString byteArrayToUnicode(const QByteArray array) {
|
||||
|
||||
@@ -87,17 +80,72 @@ int algoResult;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
QString getOriSaveFromat()
|
||||
static cv::Rect findMaxAreaContour(cv::Mat src)
|
||||
{
|
||||
return oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"
|
||||
+ "ORI_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".bmp";
|
||||
int maxIndex = 0, maxArea = 0;
|
||||
std::vector<std::vector<cv::Point>>contours;
|
||||
cv::findContours(src, contours, cv::noArray(), cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
|
||||
if (contours.size() == 0)
|
||||
return cv::Rect(0, 0, 0, 0);
|
||||
for (int i = 0; i < contours.size(); i++)
|
||||
{
|
||||
int Area = cv::contourArea(contours[i]);
|
||||
if (Area > maxArea)
|
||||
{
|
||||
maxArea = Area;
|
||||
maxIndex = i;
|
||||
}
|
||||
}
|
||||
if (contours.size() != 0)
|
||||
return cv::boundingRect(contours[maxIndex]);
|
||||
return cv::Rect(0, 0, 0, 0);
|
||||
}
|
||||
QString getResSaveFromat()
|
||||
inline std::string utf8_to_gbk(const std::string& str)
|
||||
{
|
||||
return resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//"
|
||||
+ "RES_" + cameraKey_index + "_" + QString::fromStdString(getCurrentTime()) + ".png";
|
||||
std::wstring_convert<std::codecvt_utf8<wchar_t>> conv;
|
||||
std::wstring tmp_wstr = conv.from_bytes(str);
|
||||
//GBK locale name in windows
|
||||
const char* GBK_LOCALE_NAME = ".936";
|
||||
std::wstring_convert<std::codecvt_byname<wchar_t, char, mbstate_t>> convert(new std::codecvt_byname<wchar_t, char, mbstate_t>(GBK_LOCALE_NAME));
|
||||
return convert.to_bytes(tmp_wstr);
|
||||
}
|
||||
void getAllFiles(std::string path, std::vector<std::string>& files, std::string format)
|
||||
{
|
||||
intptr_t hFile = 0;//文件句柄
|
||||
struct _finddata_t fileinfo;//文件信息
|
||||
std::string p;
|
||||
if ((hFile = _findfirst(p.assign(path).append("\\*" + format).c_str(), &fileinfo)) != -1) //文件存在
|
||||
{
|
||||
do
|
||||
{
|
||||
if ((fileinfo.attrib & _A_SUBDIR))//判断是否为文件夹
|
||||
{
|
||||
if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)//文件夹名中不含"."和".."
|
||||
{
|
||||
files.push_back(p.assign(path).append("\\").append(fileinfo.name)); //保存文件夹名
|
||||
getAllFiles(p.assign(path).append("\\").append(fileinfo.name), files, format); //递归遍历文件夹
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
files.push_back(p.assign(path).append("\\").append(fileinfo.name));//如果不是文件夹,储存文件名
|
||||
}
|
||||
} while (_findnext(hFile, &fileinfo) == 0);
|
||||
_findclose(hFile);
|
||||
}
|
||||
}
|
||||
QString getOriSaveFormat(QString SN)
|
||||
{
|
||||
QString path = oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + SN + "//";
|
||||
createDirectoryIfNotExists(path);
|
||||
return path + "ORI_" + cameraKey_index + "_" + SN + "_" + QString::fromStdString(getCurrentTime()) + ".bmp";
|
||||
}
|
||||
QString getResSaveFromat(QString SN)
|
||||
{
|
||||
QString path = resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//" + SN + "//";
|
||||
createDirectoryIfNotExists(path);
|
||||
return path + "RES_" + cameraKey_index + "_" + SN + "_" + QString::fromStdString(getCurrentTime()) + ".png";
|
||||
}
|
||||
|
||||
// 缺陷信息结构体
|
||||
typedef struct {
|
||||
QString defectName = "";//缺陷名称
|
||||
@@ -232,6 +280,8 @@ void GetStringSize(HDC hdc, const char* str, int* w, int* h)
|
||||
if (h != 0) *h = size.cy;
|
||||
}
|
||||
//在图像写中文,英文也可以写
|
||||
|
||||
|
||||
void putTextZH(cv::Mat& dst, const char* str, cv::Point org, cv::Scalar color, int fontsize,
|
||||
const char* fn = "Arial", bool italic = false, bool underline = false)
|
||||
{
|
||||
@@ -397,7 +447,7 @@ void drawDefects(cv::Mat& sourceMat, QQueue<defectInfo> defectInfoList)
|
||||
|
||||
|
||||
//判断文件夹是否存在,不存在则创建
|
||||
void Hd_AI_algo_jixing1::isDirExist(QString fullDirName)
|
||||
void Hd_AI_algo_jiXing_T::isDirExist(QString fullDirName)
|
||||
{
|
||||
QDir* photo = new QDir;
|
||||
bool exist = photo->exists(fullDirName);
|
||||
@@ -415,15 +465,15 @@ void Hd_AI_algo_jixing1::isDirExist(QString fullDirName)
|
||||
photo = nullptr;
|
||||
}
|
||||
|
||||
Hd_AI_algo_jixing1* create()
|
||||
Hd_AI_algo_jiXing_T* create()
|
||||
{
|
||||
qDebug() << "[INFO] " << " Hd_AI_algo_jixing1 create success!" ;
|
||||
return new Hd_AI_algo_jixing1;
|
||||
qDebug() << "[INFO] " << " Hd_AI_algo_jiXing_T create success!" ;
|
||||
return new Hd_AI_algo_jiXing_T;
|
||||
}
|
||||
|
||||
void destory(Hd_AI_algo_jixing1* ptr)
|
||||
void destory(Hd_AI_algo_jiXing_T* ptr)
|
||||
{
|
||||
qDebug() << "[INFO] " << "Hd_AI_algo_jixing1 destory success!";
|
||||
qDebug() << "[INFO] " << "Hd_AI_algo_jiXing_T destory success!";
|
||||
if(ptr)
|
||||
{
|
||||
delete ptr;
|
||||
@@ -431,12 +481,11 @@ void destory(Hd_AI_algo_jixing1* ptr)
|
||||
}
|
||||
}
|
||||
|
||||
Hd_AI_algo_jixing1::Hd_AI_algo_jixing1()
|
||||
Hd_AI_algo_jiXing_T::Hd_AI_algo_jiXing_T()
|
||||
{
|
||||
detect_mutex = new QMutex;
|
||||
saveStruct_mutex = new QMutex;
|
||||
ifdetectThread = false;
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
QString DirPath = "E:/testImg/source" + QString::number(i);
|
||||
@@ -456,7 +505,7 @@ Hd_AI_algo_jixing1::Hd_AI_algo_jixing1()
|
||||
}
|
||||
}
|
||||
|
||||
Hd_AI_algo_jixing1::~Hd_AI_algo_jixing1()
|
||||
Hd_AI_algo_jiXing_T::~Hd_AI_algo_jiXing_T()
|
||||
{
|
||||
ifdetectThread = false;
|
||||
Sleep(10);
|
||||
@@ -470,11 +519,12 @@ Hd_AI_algo_jixing1::~Hd_AI_algo_jixing1()
|
||||
delete saveStruct_mutex;
|
||||
saveStruct_mutex = nullptr;
|
||||
}
|
||||
|
||||
/*DestroySegObj(pSeg);
|
||||
DestroyClsObj(pCls);*/
|
||||
}
|
||||
//从类中读数据到实例对象
|
||||
bool Hd_AI_algo_jixing1::readData(std::vector<cv::Mat>&vec_mat,QByteArray &data)
|
||||
bool Hd_AI_algo_jiXing_T::readData(std::vector<cv::Mat>&vec_mat,QByteArray &data)
|
||||
{
|
||||
detect_mutex->lock();
|
||||
//qDebug() << __FUNCTION__ << " line:" <<__LINE__ << " data len:" << data.length();
|
||||
@@ -492,7 +542,8 @@ bool Hd_AI_algo_jixing1::readData(std::vector<cv::Mat>&vec_mat,QByteArray &data)
|
||||
//if (allNum++ % 2 == 0)
|
||||
// data = "2*3*2";// resByte.dequeue();
|
||||
//else
|
||||
data = QByteArray::number(algoResult) + "&" + QByteArray::number(algoResult - 1) + "+" + QByteArray::number(algoResult);//1OK,2NG
|
||||
QVariant jiXingJieGuo = (resultPlc == "1") ? "OK" : "NG";
|
||||
data = logicUiTransport::encodeAllData(SN,{ resultPlc }, { {"极性检测结果",jiXingJieGuo} });
|
||||
resByte.clear();
|
||||
////之后根据结果类修改
|
||||
//if(resIfNg == true)
|
||||
@@ -507,7 +558,7 @@ bool Hd_AI_algo_jixing1::readData(std::vector<cv::Mat>&vec_mat,QByteArray &data)
|
||||
return true;
|
||||
}
|
||||
//从类中读数据到实例对象
|
||||
bool Hd_AI_algo_jixing1::encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte)
|
||||
bool Hd_AI_algo_jiXing_T::encodeResultValue(QVector<std::string> append_value,QByteArray &resultByte)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -544,9 +595,10 @@ bool Hd_AI_algo_jixing1::encodeResultValue(QVector<std::string> append_value,QBy
|
||||
int myallNum[4] = {0};
|
||||
QMap<int, cv::Mat> lastImgMap;
|
||||
//接收数据
|
||||
bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &data)
|
||||
bool Hd_AI_algo_jiXing_T::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &data)
|
||||
{
|
||||
//qDebug() << __FUNCTION__ << "line:"<< __LINE__ << " data len" << data.length() ;
|
||||
|
||||
if(vec_mat.empty())
|
||||
{
|
||||
qCritical() << "[Error] " << " vec_mat is null !";
|
||||
@@ -557,7 +609,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
for (int i = 0; i < vec_mat.size(); i++)
|
||||
HikMat.enqueue(vec_mat[i]);
|
||||
|
||||
QByteArray source_savePath;
|
||||
QByteArray source_savePath;
|
||||
QByteArray sData = data;
|
||||
QByteArrayList splitDataList = sData.split(',');
|
||||
if (splitDataList.size() >= 4)
|
||||
@@ -568,6 +620,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
isDirExist(byteArrayToUnicode(saveDir)); //不存在,创建
|
||||
QString sdataTime= QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||||
source_savePath = splitDataList[0] + "/" + splitDataList[1] + "/" + sdataTime.toLocal8Bit() + "-" + splitDataList[2] + "-" + splitDataList[3];// +".bmp";
|
||||
SN = splitDataList[3];
|
||||
}
|
||||
//int index = -1;
|
||||
/*if (sData.contains("offline-camera0"))
|
||||
@@ -591,11 +644,24 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
savePath = "E:\\testImg\\source3\\" + QString::number(myallNum[3]++) + ".bmp";
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
|
||||
createDirectoryIfNotExists(oriImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//");
|
||||
addImgToSaveStruct(HikMat[0], "0", getOriSaveFromat());//保存原图
|
||||
addImgToSaveStruct(HikMat[0], "0", getOriSaveFormat(SN));//保存原图
|
||||
//if (!source_savePath.isEmpty())
|
||||
//{
|
||||
// //std::cout << "try savePath::" << savePath.toStdString() << std::endl;
|
||||
// //测试相机的,
|
||||
// //while (HikMat[0].cols > 2000)cv::resize(HikMat[0], HikMat[0], cv::Size(), 0.08, 0.08);'
|
||||
// for (int i = 0; i < initValueList.size(); i++)
|
||||
// {
|
||||
// QString minit = byteArrayToUnicode(initValueList[i]);
|
||||
// if (initValueList[i].contains(data.split(',')[2].split('_')[0]))
|
||||
// if (initValueList[i].contains(QString("原图_保存").toLocal8Bit()))
|
||||
// {
|
||||
// addImgToSaveStruct(HikMat[0], "0", byteArrayToUnicode(source_savePath + ".bmp"));//保存原图
|
||||
// if (HikMat.size() == 2)//3D
|
||||
// addImgToSaveStruct(HikMat[1], "0", byteArrayToUnicode(source_savePath + ".tif"));
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
//if (myallNum[index] == 1)
|
||||
//{
|
||||
@@ -646,7 +712,7 @@ bool Hd_AI_algo_jixing1::writeData(std::vector<cv::Mat>& vec_mat, QByteArray &da
|
||||
|
||||
//传入initParas函数,格式为:相机key+参数名1#参数值1#参数值2+参数名2#参数值1...
|
||||
//初始化
|
||||
bool Hd_AI_algo_jixing1::initParas(QByteArray& byte)
|
||||
bool Hd_AI_algo_jiXing_T::initParas(QByteArray& byte)
|
||||
{
|
||||
initValueList = byte.split('+');
|
||||
QStringList valueiList;
|
||||
@@ -671,13 +737,11 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte)
|
||||
valueiList.append(valuei);
|
||||
}
|
||||
|
||||
|
||||
/*pSeg = CreateSegObjS(pSeg_modulePath, 128, gpuId);
|
||||
pCls = CreateClsObjV3(pCls_modulePath, gpuId, 1);*/
|
||||
|
||||
|
||||
//StationNo = vec_ret.at(0).toInt();
|
||||
|
||||
//InitThreads(StationNo, img2D);
|
||||
//InitModels(StationNo, img2D);
|
||||
|
||||
@@ -686,9 +750,9 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte)
|
||||
|
||||
//线程检测:结果类完成时,使用
|
||||
//ifThreadRunDetect = true;
|
||||
//QFuture<void> future1 = QtConcurrent::run(this, &Hd_AI_algo_jixing1::detectThread);
|
||||
//QFuture<void> future1 = QtConcurrent::run(this, &Hd_AI_algo_jiXing_T::detectThread);
|
||||
//运行存图线程
|
||||
QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_algo_jixing1::saveImgThread);
|
||||
QFuture<void> future2 = QtConcurrent::run(this, &Hd_AI_algo_jiXing_T::saveImgThread);
|
||||
//detectThread();
|
||||
|
||||
//原图总文件夹
|
||||
@@ -698,12 +762,12 @@ bool Hd_AI_algo_jixing1::initParas(QByteArray& byte)
|
||||
//结果图总文件夹
|
||||
isDirExist(resImgSaveDir);
|
||||
|
||||
myEngine.SetProcedurePath("./halconFilesAlgo/AlgoLibrary_628_1.hdpl"); //设置hdvp路径
|
||||
//qDebug() << "[INFO] " << " StationNo:" << StationNo << " img2D:" << img2D ;
|
||||
myEngine.SetProcedurePath("./halconFilesAlgo/JX_ColorInspection.hdpl"); //设置hdvp路径
|
||||
return true;
|
||||
}
|
||||
// 解码
|
||||
bool Hd_AI_algo_jixing1::decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret)
|
||||
bool Hd_AI_algo_jiXing_T::decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret)
|
||||
{
|
||||
if(byte.isEmpty())
|
||||
{
|
||||
@@ -737,12 +801,13 @@ bool Hd_AI_algo_jixing1::decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//---------检测流程,根据实际项目修改---------
|
||||
bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime)
|
||||
bool Hd_AI_algo_jiXing_T::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDir2D, QString mySN, QString myDataTime)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
|
||||
//存图数据加保存队列,加锁,避免数据访问冲突
|
||||
saveStruct_mutex->lock();
|
||||
saveImgStruct mySave;
|
||||
@@ -769,68 +834,84 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
// csvName.write(lines[i].toStdString().c_str());
|
||||
// csvName.close();
|
||||
//}
|
||||
HDevEngineCpp::HDevProcedure proc("YH_Color_Inspection");
|
||||
HDevProcedureCall procedureCall(proc);
|
||||
QQueue<defectInfo> defectInfoList;
|
||||
|
||||
//sourceImg = cv::imread("D:\\mySN15-46-33-86.bmp",-1);
|
||||
//sourceImg = cv::imread("F:/CCD/TEST/20241024-091531.bmp", -1);
|
||||
cv::Mat Paint;
|
||||
sourceImg.copyTo(Paint);
|
||||
//极性检测
|
||||
if(Paint.channels() == 1)
|
||||
cvtColor(Paint, Paint, COLOR_GRAY2BGR);
|
||||
|
||||
|
||||
HDevEngineCpp::HDevProcedure proc("JX_Inspection");
|
||||
HDevProcedureCall procedureCall(proc);
|
||||
|
||||
HObject in_Image;
|
||||
HTuple out_ColorType;
|
||||
HTuple out_Flag;
|
||||
HTuple out_Flag, out_ColorType;
|
||||
MatToHObject(sourceImg, &in_Image);
|
||||
procedureCall.SetInputIconicParamObject("in_Image", in_Image);//设置输入图像类变量
|
||||
|
||||
procedureCall.SetInputIconicParamObject("in_Image", in_Image);//
|
||||
procedureCall.Execute();//执行halcon程序
|
||||
out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出图像类变量
|
||||
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出控制类变量
|
||||
//相机2 OK为铜 NG为铝
|
||||
if (out_Flag.D() == 1)
|
||||
|
||||
out_Flag = procedureCall.GetOutputCtrlParamTuple("out_Flag");//获取输出图像类变量
|
||||
out_ColorType = procedureCall.GetOutputCtrlParamTuple("out_ColorType");//获取输出控制类变量
|
||||
resultPlc = "1";
|
||||
if(out_Flag.D() == 1)
|
||||
{
|
||||
if (out_ColorType.D() == 2)//铝
|
||||
int res1 = out_ColorType[0].D();
|
||||
int res2 = out_ColorType[1].D();
|
||||
//1铜 2铝+
|
||||
switch (res1)
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("铝极").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300);
|
||||
//cv::putText(sourceImg, "Aluminium", cv::Point(0, 240), 2, 10, cv::Scalar(0, 255, 0), 10);
|
||||
cv::putText(Paint, "NG", cv::Point(0, 550), 2, 10, cv::Scalar(0, 0, 255), 10);
|
||||
algoResult = 1;
|
||||
//Result = 1 ? 2;
|
||||
//Result = 1;
|
||||
case 0:
|
||||
putTextHusky(Paint, utf8_to_gbk("异常").c_str(), cv::Point(0, 0), cv::Scalar(0, 0, 255), 300);
|
||||
break;
|
||||
case 1:
|
||||
putTextHusky(Paint, utf8_to_gbk("铜").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 500);
|
||||
break;
|
||||
case 2:
|
||||
putTextHusky(Paint, utf8_to_gbk("铝").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 500);
|
||||
break;
|
||||
}
|
||||
else if (out_ColorType.D() == 1)//铜
|
||||
|
||||
switch (res2)
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("铜极").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300);
|
||||
//cv::putText(sourceImg, "Copper", cv::Point(0, 240), 2, 10, cv::Scalar(0, 255, 0), 10);
|
||||
cv::putText(Paint, "OK", cv::Point(0, 550), 2, 10, cv::Scalar(0, 255, 0), 10);
|
||||
algoResult = 1;
|
||||
case 0:
|
||||
putTextHusky(Paint, utf8_to_gbk("异常").c_str(), cv::Point(0, Paint.rows - 500), cv::Scalar(0, 0, 255), 300);
|
||||
break;
|
||||
case 1:
|
||||
putTextHusky(Paint, utf8_to_gbk("铜").c_str(), cv::Point(0, Paint.rows - 500), cv::Scalar(0, 255, 0), 500);
|
||||
break;
|
||||
case 2:
|
||||
putTextHusky(Paint, utf8_to_gbk("铝").c_str(), cv::Point(0, Paint.rows - 500), cv::Scalar(0, 255, 0), 500);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
//T 为铜OK,L为铝OK
|
||||
if (res1 == 1 && res2 == 1)//铜ok
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("OK").c_str(), cv::Point(Paint.cols - 800, 0), cv::Scalar(0, 255, 0), 500);
|
||||
}
|
||||
else
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300);
|
||||
// cv::putText(sourceImg, "Algo error1", cv::Point(0, 240), 2, 10, cv::Scalar(0, 0, 255), 10);
|
||||
//Result = 2;
|
||||
putTextHusky(Paint, utf8_to_gbk("NG").c_str(), cv::Point(Paint.cols - 800, 0), cv::Scalar(0, 0, 255), 500);
|
||||
resultPlc = "1";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
putTextHusky(Paint, utf8_to_gbk("算法异常1").c_str(), cv::Point(0, 0), cv::Scalar(0, 255, 0), 300);
|
||||
// cv::putText(sourceImg, "Algo error2", cv::Point(0, 240), 2, 10, cv::Scalar(0, 0, 255), 10);
|
||||
}
|
||||
putTextHusky(Paint, utf8_to_gbk("NG1").c_str(), cv::Point(0, 50), cv::Scalar(0, 0, 255), 500);
|
||||
|
||||
/* ho_Image.Clear();
|
||||
hv_out_Value.Clear();
|
||||
hv_Make.Clear();*/
|
||||
|
||||
QQueue<defectInfo> defectInfoList;
|
||||
|
||||
|
||||
detect_mutex->lock();
|
||||
//resMat = sourceImg.clone();
|
||||
//sourceImg.copyTo(resMat);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
resMat.push_back(Paint);
|
||||
//结果图画框和缺陷,在resMat上绘制
|
||||
if (resMat.size() > 0)
|
||||
drawDefects(resMat[0], defectInfoList);
|
||||
|
||||
//QByteArray,根据实际项目进行解析
|
||||
//参数,例:返回结果图;相机关键字(SN或userID)+保存路径+缺陷信息列表(缺陷名称,缺陷位置int(x,y,w,h),画框颜色Scalar(a,b,c),缺陷面积double)
|
||||
|
||||
QJsonArray detaillists;
|
||||
//QByteArrayList resQbyte;
|
||||
for (int i = 0; i < defectInfoList.size(); i++)
|
||||
@@ -852,7 +933,7 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
detailObj.insert("defectRect.width", QString::number(mdefect.defectRect.width));
|
||||
detailObj.insert("defectRect.height", QString::number(mdefect.defectRect.height));
|
||||
detailObj.insert("defectScalar0", QString::number(mdefect.defectScalar[0]));
|
||||
detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1]));
|
||||
detailObj.insert("defectScalar1", QString::number(mdefect.defectScalar[1]));
|
||||
detailObj.insert("defectScalar2", QString::number(mdefect.defectScalar[2]));
|
||||
detailObj.insert("defectArea", QString::number(mdefect.defectArea));
|
||||
detailObj.insert("defectLength", QString::number(sqrt(mdefect.defectRect.width* mdefect.defectRect.width+ mdefect.defectRect.height* mdefect.defectRect.height)));
|
||||
@@ -868,14 +949,13 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
//emit sendResultData(resMat, resQbyte);
|
||||
//resQbyte.clear();
|
||||
|
||||
isDirExist(resImgSaveDir + mysaveKey1 + "/");
|
||||
QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png";
|
||||
//isDirExist(resImgSaveDir + mysaveKey1 + "/");
|
||||
QString qimgsavePath = resImgSaveDir + mysaveKey1 + "/" + mySN + myDataTime + ".png";
|
||||
//存图数据入队,按需
|
||||
QString sdataTime = QDateTime::currentDateTime().toString("yyyy-MM-dd-hh-mm-ss-zzz");
|
||||
if (resMat.size() > 0)
|
||||
if (resMat.size() > 0 )
|
||||
{
|
||||
createDirectoryIfNotExists(resImgSaveDir + getCurrentDate() + "//" + getCurrentHour() + "//");
|
||||
addImgToSaveStruct(resMat[0], "0", getResSaveFromat());//保存原图
|
||||
addImgToSaveStruct(resMat[0], "0", getResSaveFromat(SN));//保存原图
|
||||
}
|
||||
detect_mutex->unlock();
|
||||
|
||||
@@ -919,7 +999,7 @@ bool Hd_AI_algo_jixing1::AIdetect(cv::Mat img2D, QString mysaveKey, QString myDi
|
||||
}
|
||||
|
||||
//存图加入队列
|
||||
void Hd_AI_algo_jixing1::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath)
|
||||
void Hd_AI_algo_jiXing_T::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QString savePath)
|
||||
{
|
||||
//存图数据加保存队列,加锁,避免数据访问冲突
|
||||
saveStruct_mutex->lock();
|
||||
@@ -931,7 +1011,7 @@ void Hd_AI_algo_jixing1::addImgToSaveStruct(cv::Mat img2D, QString mysaveKey, QS
|
||||
saveStruct.enqueue(mySave);
|
||||
saveStruct_mutex->unlock();
|
||||
}
|
||||
void Hd_AI_algo_jixing1::saveImgThread()
|
||||
void Hd_AI_algo_jiXing_T::saveImgThread()
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
@@ -961,7 +1041,7 @@ void Hd_AI_algo_jixing1::saveImgThread()
|
||||
}
|
||||
}
|
||||
//检测线程,应当只运行一次
|
||||
void Hd_AI_algo_jixing1::detectThread()
|
||||
void Hd_AI_algo_jiXing_T::detectThread()
|
||||
{
|
||||
do
|
||||
{
|
||||
@@ -997,7 +1077,7 @@ void Hd_AI_algo_jixing1::detectThread()
|
||||
}
|
||||
|
||||
//测试相机的,
|
||||
//while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5);
|
||||
// while (sourceImg1.cols > 2000)cv::resize(sourceImg1, sourceImg1, cv::Size(), 0.5, 0.5);
|
||||
|
||||
//存图数据入队
|
||||
//addImgToSaveStruct(sourceImg1, mysaveKey, oriImgSaveDir + mysaveKey + "/" + mySN + myDataTime + ".bmp");
|
||||
@@ -1017,7 +1097,7 @@ void Hd_AI_algo_jixing1::detectThread()
|
||||
}
|
||||
|
||||
static int runNum = 0;
|
||||
bool Hd_AI_algo_jixing1::run()
|
||||
bool Hd_AI_algo_jiXing_T::run()
|
||||
{
|
||||
clock_t start, stop;
|
||||
start = clock();
|
||||
@@ -1032,7 +1112,7 @@ bool Hd_AI_algo_jixing1::run()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Hd_AI_algo_jixing1::checkStatus()
|
||||
bool Hd_AI_algo_jiXing_T::checkStatus()
|
||||
{
|
||||
status = moduleStatus;
|
||||
return status;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef Hd_AI_algo_jixing1_H
|
||||
#define Hd_AI_algo_jixing1_H
|
||||
#ifndef Hd_AI_algo_jiXing_T_H
|
||||
#define Hd_AI_algo_jiXing_T_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <atlstr.h>
|
||||
@@ -15,15 +15,13 @@
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
#include <halconcpp/HalconCpp.h>
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include "imgproc/imgproc_c.h"
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
#include <HDevEngineCpp.h>
|
||||
|
||||
using namespace HDevEngineCpp;
|
||||
|
||||
|
||||
@@ -35,14 +33,14 @@ struct saveImgStruct;
|
||||
// std::string savePath; //保存路径
|
||||
//};
|
||||
|
||||
//初始化流程(一次):Hd_AI_algo_jixing1,initParas
|
||||
//初始化流程(一次):Hd_AI_algo_jiXing_T,initParas
|
||||
//运行流程:writeData主线程把数据传过来,run,readData此线程把数据传主线程
|
||||
class Hd_AI_algo_jixing1 :public Base
|
||||
class Hd_AI_algo_jiXing_T :public Base
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
Hd_AI_algo_jixing1();
|
||||
virtual ~Hd_AI_algo_jixing1();
|
||||
Hd_AI_algo_jiXing_T();
|
||||
virtual ~Hd_AI_algo_jiXing_T();
|
||||
//从类中读数据到实例对象
|
||||
bool readData(std::vector<cv::Mat>&,QByteArray&);
|
||||
//实例对象把数据写入到类
|
||||
@@ -57,8 +55,6 @@ public:
|
||||
bool decodeAiValue(QByteArray byte,QVector<QByteArray> &vec_ret);
|
||||
//---------检测流程,根据实际项目修改---------
|
||||
bool AIdetect(cv::Mat img2D, QString saveKey, QString Dir2D, QString SN, QString DataTime);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
HDevEngine myEngine;
|
||||
@@ -107,8 +103,8 @@ private:
|
||||
|
||||
extern "C"
|
||||
{
|
||||
Q_DECL_EXPORT Hd_AI_algo_jixing1 * create();
|
||||
Q_DECL_EXPORT void destory(Hd_AI_algo_jixing1 * ptr);
|
||||
Q_DECL_EXPORT Hd_AI_algo_jiXing_T * create();
|
||||
Q_DECL_EXPORT void destory(Hd_AI_algo_jiXing_T * ptr);
|
||||
}
|
||||
//保存图片的结构体
|
||||
struct saveImgStruct
|
||||
|
||||
@@ -37,8 +37,8 @@ FILE(GLOB SRC_FILES "./*.cpp")
|
||||
FILE(GLOB UI_FILES "./*.ui")
|
||||
|
||||
#find_package(Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core REQUIRED)
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Sql REQUIRED)
|
||||
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Sql REQUIRED)
|
||||
|
||||
add_compile_options("$<$<C_COMPILER_ID:MSVC>:/utf-8>")
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
@@ -59,6 +59,7 @@ target_link_libraries(Hd_LogicDll_module PRIVATE
|
||||
${qt_target_link}
|
||||
${opencv_target_link}
|
||||
Qt${QT_VERSION_MAJOR}::Core
|
||||
Qt${QT_VERSION_MAJOR}::Sql
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -810,14 +810,11 @@ bool Logic_taskthread::deleteSnData ( QByteArray byteArray, QVector<QString>& sn
|
||||
// 算法结果 写入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); // 存储结果的
|
||||
|
||||
QByteArrayList PLCvec_ret= logicUiTransport::decodePlcResult(byteArray); // 存储结果的
|
||||
std::map<QString, QVariant> CsvAndChartData =
|
||||
logicUiTransport::decodeCsvAndChartData(byteArray);//发送导表格或者数据库的
|
||||
_CsvWriter.addtData(CsvAndChartData["条码"].toString(), CsvAndChartData);//写入csv文件
|
||||
|
||||
if (PLCvec_ret.isEmpty() )
|
||||
{
|
||||
qCritical() << __FUNCTION__ << " line:" << __LINE__ << " vec_ret is null!";
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include "struct.h"
|
||||
|
||||
#include <rlib/rlib_writeCsv.h>
|
||||
#pragma execution_character_set("utf-8") //能够正常显示中文字符串
|
||||
class Logic_taskthread : public QThread
|
||||
{
|
||||
@@ -81,6 +81,7 @@ public:
|
||||
QString CmdHeadShort = "write_short_";
|
||||
QString CmdHeadString = "write_string_";
|
||||
private:
|
||||
CsvWriter _CsvWriter;
|
||||
QQueue<dataPack> taskImageDataPack;
|
||||
QMutex* task_image_lock = nullptr;
|
||||
int mysaveimagethreadindex = -1;
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
#include <rlib_writeCsv.h>
|
||||
|
||||
@@ -0,0 +1,518 @@
|
||||
#include <qfile.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
#include <qdatetime.h>
|
||||
#include <memory>
|
||||
#include <qtextstream.h>
|
||||
#include <QtSql/QSqlDatabase>
|
||||
#include <QtSql/QSqlQuery>
|
||||
#include <QtSql/QSqlError>
|
||||
#include <QtSql/QSqlRecord>
|
||||
#include <QVariant>
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
#include <QMap>
|
||||
#include <qcoreapplication.h>
|
||||
#include <qdir.h>
|
||||
#include <qtimer.h>
|
||||
#include <chrono>
|
||||
#include <qobject.h>
|
||||
class SQLiteDB {
|
||||
public:
|
||||
SQLiteDB(const QString& dbPath, const QString& dbName) : m_dbName(dbName), m_dbPath(dbPath) { connect(); }
|
||||
~SQLiteDB() {};
|
||||
bool connect() {
|
||||
// 检查数据库文件是否存在
|
||||
if (!QFile::exists(m_dbPath + m_dbName + ".db")) {
|
||||
QDir().mkpath(m_dbPath);
|
||||
qDebug() << "Database file does not exist. Creating a new database:" << m_dbName;
|
||||
}
|
||||
QCoreApplication::addLibraryPath("./");
|
||||
// 添加 SQLite 数据库驱动
|
||||
m_db = QSqlDatabase::addDatabase("QSQLITE");
|
||||
m_db.setDatabaseName(m_dbPath + m_dbName + ".db");
|
||||
|
||||
// 打开数据库
|
||||
if (!m_db.open()) {
|
||||
qCritical() << "Failed to open or create database:" << m_db.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
qDebug() << "Connected to SQLite database:" << m_dbPath + m_dbName;
|
||||
createTable("setting",
|
||||
{
|
||||
{"id","INTEGER PRIMARY KEY AUTOINCREMENT"} ,
|
||||
});
|
||||
return true;
|
||||
}
|
||||
// 关闭数据库连接
|
||||
void disconnect() {
|
||||
if (m_db. isOpen()) {
|
||||
m_db.close();
|
||||
qDebug() << "Database closed.";
|
||||
}
|
||||
}
|
||||
// 执行无返回值的SQL语句(如插入、删除、更新)
|
||||
bool execute(const QString& queryStr, const QVariantList& args = {}) {
|
||||
QSqlQuery query;
|
||||
query.prepare(queryStr);
|
||||
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
query.bindValue(i, args[i]);
|
||||
}
|
||||
|
||||
if (!query.exec()) {
|
||||
qCritical() << "SQL error:" << query.lastError().text();
|
||||
qCritical() << "Query:" << queryStr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// 查询数据,返回结果集
|
||||
QList<QMap<QString, QVariant>> query(const QString& queryStr, const QVariantList& args = {}) {
|
||||
QList<QMap<QString, QVariant>> results;
|
||||
QSqlQuery query;
|
||||
query.prepare(queryStr);
|
||||
|
||||
for (int i = 0; i < args.size(); ++i) {
|
||||
query.bindValue(i, args[i]);
|
||||
}
|
||||
|
||||
if (!query.exec()) {
|
||||
qCritical() << "SQL error:" << query.lastError().text();
|
||||
qCritical() << "Query:" << queryStr;
|
||||
return results;
|
||||
}
|
||||
|
||||
while (query.next()) {
|
||||
QMap<QString, QVariant> row;
|
||||
for (int i = 0; i < query.record().count(); ++i) {
|
||||
row.insert(query.record().fieldName(i), query.value(i));
|
||||
}
|
||||
results.append(row);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
// 检查数据库是否已连接
|
||||
bool isConnected() const {
|
||||
return m_db.isOpen();
|
||||
}
|
||||
////////////////BASE//////////////////////
|
||||
bool createTable(const QString& tableName, const QList<std::pair<QString, QString>>& columns) {
|
||||
if (columns.empty()) {
|
||||
qDebug() << "Create table failed: columns are empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList columnDefinitions;
|
||||
for (const auto& pair : columns) {
|
||||
columnDefinitions << QString("%1 %2").arg(pair.first).arg(pair.second);
|
||||
}
|
||||
|
||||
// 确保表名被双引号包围,处理特殊字符的表名
|
||||
QString sql = QString("CREATE TABLE IF NOT EXISTS \"%1\" (%2)")
|
||||
.arg(tableName)
|
||||
.arg(columnDefinitions.join(", "));
|
||||
|
||||
return execute(sql);
|
||||
}
|
||||
|
||||
bool dropTable(const QString& tableName) {
|
||||
QString sql = QString("DROP TABLE IF EXISTS %1").arg(tableName);
|
||||
return execute(sql);
|
||||
}
|
||||
bool tableExists(const QString& tableName) {
|
||||
// 使用 sqlite_master 查询表是否存在
|
||||
QString sql = QString("SELECT name FROM sqlite_master WHERE type='table' AND name='%1';").arg(tableName);
|
||||
|
||||
QList<QMap<QString, QVariant>> result = query(sql);
|
||||
return !result.isEmpty(); // 如果结果不为空,则表示表存在
|
||||
}
|
||||
|
||||
bool _insert(const QString& tableName,
|
||||
const std::map<QString, QVariant>& data) {
|
||||
// 如果数据为空,返回 false
|
||||
if (data.empty()) {
|
||||
qDebug() << "Insert failed: data is empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果表名为空,返回 false
|
||||
if (tableName.isEmpty()) {
|
||||
qDebug() << "Insert failed: tableName is empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList columns, values;
|
||||
for (const auto& pair : data) {
|
||||
columns << pair.first;
|
||||
// 直接插入数据(明文传输),需要确保数据已经适当转义
|
||||
values << "'" + pair.second.toString().replace("'", "''") + "'"; // 处理引号
|
||||
}
|
||||
|
||||
// 构造 SQL 查询语句(不使用绑定参数)
|
||||
QString sql = QString("INSERT INTO \"%1\" (%2) VALUES (%3)")
|
||||
.arg(tableName) // 使用双引号包围表名,确保兼容特殊字符
|
||||
.arg(columns.join(", "))
|
||||
.arg(values.join(", "));
|
||||
|
||||
qDebug() << "Generated SQL: " << sql;
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
|
||||
// 检查数据库连接
|
||||
if (!m_db.isOpen()) {
|
||||
qDebug() << "Database is not open!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并检查错误
|
||||
if (!query.exec(sql)) {
|
||||
qDebug() << "Insert failed:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool _update(const QString& tableName,
|
||||
const std::map<QString, QVariant>& data,
|
||||
const std::map<QString, QVariant>& conditions) {
|
||||
if (data.empty() || conditions.empty()) {
|
||||
qDebug() << "Update failed: data or conditions are empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList setClauses;
|
||||
for (const auto& pair : data) {
|
||||
QString value = pair.second.toString().replace("'", "''"); // 防止单引号注入
|
||||
setClauses << QString("%1 = '%2'").arg(pair.first).arg(value);
|
||||
}
|
||||
|
||||
QStringList whereClauses;
|
||||
for (const auto& pair : conditions) {
|
||||
QString conditionValue = pair.second.toString().replace("'", "''");
|
||||
whereClauses << QString("%1 = '%2'").arg(pair.first).arg(conditionValue);
|
||||
}
|
||||
|
||||
// 构造 SQL 查询语句(不使用绑定参数)
|
||||
QString sql = QString("UPDATE \"%1\" SET %2 WHERE %3")
|
||||
.arg(tableName)
|
||||
.arg(setClauses.join(", "))
|
||||
.arg(whereClauses.join(" AND "));
|
||||
|
||||
qDebug() << "Generated SQL: " << sql;
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
|
||||
// 检查数据库连接
|
||||
if (!m_db.isOpen()) {
|
||||
qDebug() << "Database is not open!";
|
||||
return false;
|
||||
}
|
||||
|
||||
// 执行查询并检查错误
|
||||
if (!query.exec(sql)) {
|
||||
qDebug() << "Update failed:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool _delete(const QString& tableName,
|
||||
const std::map<QString, QVariant>& conditions) {
|
||||
if (conditions.empty()) {
|
||||
qDebug() << "Delete failed: conditions are empty.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList whereClauses;
|
||||
for (const auto& pair : conditions) {
|
||||
whereClauses << QString("%1 = :%2").arg(pair.first).arg(pair.first + "_condition");
|
||||
}
|
||||
|
||||
QString sql = QString("DELETE FROM \"%1\" WHERE %2")
|
||||
.arg(tableName)
|
||||
.arg(whereClauses.join(" AND "));
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
query.prepare(sql);
|
||||
|
||||
// 绑定条件参数
|
||||
for (const auto& pair : conditions) {
|
||||
query.bindValue(":" + pair.first + "_condition", QVariant::fromValue(pair.second));
|
||||
}
|
||||
|
||||
if (!query.exec()) {
|
||||
qDebug() << "Delete failed:" << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::map<QString, QVariant>> _search(const QString& tableName,
|
||||
const QStringList& columns,
|
||||
const std::map<QString, QVariant>& conditions = {}) {
|
||||
// 如果没有指定列名,则选择所有列
|
||||
QStringList selectColumns = columns.isEmpty() ? QStringList("*") : columns;
|
||||
|
||||
// 构建基本的 SQL 查询
|
||||
QString sql = QString("SELECT %1 FROM \"%2\"").arg(selectColumns.join(", "), tableName);
|
||||
|
||||
if (!conditions.empty()) {
|
||||
QStringList whereClauses;
|
||||
for (const auto& pair : conditions) {
|
||||
// 直接拼接条件,确保值已经处理好以防 SQL 注入
|
||||
QString value = pair.second.toString().replace("'", "''"); // 防止单引号注入
|
||||
whereClauses << QString("%1 = '%2'").arg(pair.first).arg(value);
|
||||
}
|
||||
sql += " WHERE " + whereClauses.join(" AND ");
|
||||
}
|
||||
|
||||
qDebug() << "Generated SQL: " << sql;
|
||||
|
||||
QSqlQuery query(m_db);
|
||||
|
||||
// 检查数据库连接
|
||||
if (!m_db.isOpen()) {
|
||||
qDebug() << "Database is not open!";
|
||||
return {};
|
||||
}
|
||||
|
||||
// 执行查询并检查错误
|
||||
if (!query.exec(sql)) {
|
||||
qDebug() << "Search failed:" << query.lastError().text();
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<std::map<QString, QVariant>> results;
|
||||
while (query.next()) {
|
||||
std::map<QString, QVariant> row;
|
||||
for (int i = 0; i < query.record().count(); ++i) {
|
||||
row[query.record().fieldName(i)] = query.value(i);
|
||||
}
|
||||
results.push_back(row);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
///////////////////EX//FUNC/////////////////
|
||||
bool exportTableToCSV(const QString& tableName, const QString& filePath, std::mutex& _mutex) {
|
||||
using namespace std::chrono; // 便于使用 chrono 相关功能
|
||||
// 记录开始时间
|
||||
auto start = high_resolution_clock::now();
|
||||
// 查询表中的所有数据
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
QString csvFileName = filePath + "/" + tableName + ".csv";
|
||||
QString sql = QString("SELECT * FROM \"%1\"").arg(tableName);
|
||||
QSqlQuery query(m_db);
|
||||
|
||||
if (!query.exec(sql)) {
|
||||
qCritical() << "Query execution failed: " << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
// 如果查询没有返回数据,返回 false
|
||||
if (!query.next()) {
|
||||
qDebug() << "No data found in table" << tableName;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 打开文件进行写入
|
||||
QFile file(csvFileName);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qCritical() << "Failed to open file" << csvFileName;
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&file);
|
||||
|
||||
// 获取列名顺序
|
||||
QSqlRecord record = query.record();
|
||||
QStringList columns;
|
||||
for (int i = 0; i < record.count(); ++i) {
|
||||
columns << record.fieldName(i); // 保证列名按查询结果顺序提取
|
||||
}
|
||||
|
||||
// 写入表头(列名)
|
||||
out << columns.join(",") << "\n"; // 表头以逗号分隔
|
||||
|
||||
// 写入数据行
|
||||
do {
|
||||
QStringList values;
|
||||
for (const auto& column : columns) {
|
||||
values << query.value(column).toString(); // 获取每列的值,保持列名顺序
|
||||
}
|
||||
out << values.join(",") << "\n"; // 每行数据以逗号分隔
|
||||
} while (query.next()); // 循环处理所有数据行
|
||||
|
||||
file.close(); // 关闭文件
|
||||
// 记录结束时间
|
||||
auto end = high_resolution_clock::now();
|
||||
|
||||
// 计算耗时
|
||||
auto duration = duration_cast<milliseconds>(end - start);
|
||||
qDebug() << csvFileName << "EXPORT CSV COST: " << duration.count() << "ms";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
QString m_dbName;
|
||||
QString m_dbPath;
|
||||
QSqlDatabase m_db;
|
||||
};
|
||||
|
||||
class CsvWriter : public QThread
|
||||
{
|
||||
public:
|
||||
CsvWriter():
|
||||
_db("./sqlDatabse/", "database")
|
||||
{
|
||||
init();
|
||||
startAutoExport(60000);
|
||||
}
|
||||
void addtData(const QString& snCode ,const std::map<QString, QVariant>& data) {
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
auto res = _db._search(getCurrentProcessCsvName(), {}, {{"条码",snCode}});
|
||||
if (res.empty() == true)//当前数据为空时查询过去的数据是否为空
|
||||
{
|
||||
auto lastRes = _db._search(getLastProcessCsvName(), {}, { {"条码",snCode} });
|
||||
if (lastRes.empty() == true)//过去的数据也为空 则视作现在要插入的数据为全新的数据
|
||||
{
|
||||
std::map<QString, QVariant> insertData = data;
|
||||
insertData["条码"] = snCode;
|
||||
insertData["创建时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
insertData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
_db._insert(getCurrentProcessCsvName(), insertData);
|
||||
}
|
||||
else//过去的数据不为空 更新到过去的数据上
|
||||
{
|
||||
std::map<QString, QVariant> updateData = data;
|
||||
updateData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
_db._update(getLastProcessCsvName(), updateData, { {"条码",snCode} });
|
||||
}
|
||||
|
||||
}
|
||||
else//当前数据不为空 更新到当前数据上
|
||||
{
|
||||
std::map<QString, QVariant> updateData = data;
|
||||
updateData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
|
||||
_db._update(getCurrentProcessCsvName(), updateData, { {"条码",snCode} });
|
||||
}
|
||||
}
|
||||
private:
|
||||
void run()
|
||||
{
|
||||
while (m_running)
|
||||
{
|
||||
QThread::msleep(m_intervalMs);
|
||||
exportCsv();
|
||||
}
|
||||
}
|
||||
std::mutex _mutex;
|
||||
SQLiteDB _db;
|
||||
int m_intervalMs = 60000;
|
||||
bool m_running = true;
|
||||
QList<std::pair<QString, QString>> db_InitColumns = {
|
||||
{"条码", "TEXT NOT NULL PRIMARY KEY"},
|
||||
{"创建时间", "TEXT"},
|
||||
{"修改时间", "TEXT"},
|
||||
{ "极性检测结果","TEXT" }
|
||||
};
|
||||
QTimer* timer;
|
||||
void init()
|
||||
{
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
if (_db.createTable(getLastProcessCsvName(), db_InitColumns)) {
|
||||
qDebug() << "Table 'users' created successfully.";
|
||||
}
|
||||
else {
|
||||
qDebug() << "Failed to create table 'users'.";
|
||||
}
|
||||
if (_db.createTable(getCurrentProcessCsvName(), db_InitColumns)) {
|
||||
qDebug() << "Table 'users' created successfully.";
|
||||
}
|
||||
else {
|
||||
qDebug() << "Failed to create table 'users'.";
|
||||
}
|
||||
}
|
||||
QString getCurrentProcessCsvName(){
|
||||
// 获取当前时间
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
|
||||
// 获取当前小时和分钟
|
||||
int hour = currentDateTime.time().hour();
|
||||
int minute = currentDateTime.time().minute();
|
||||
|
||||
// 判断是否在白班时间范围(8:30到20:30)
|
||||
bool isDayShift = (hour > 8 || (hour == 8 && minute >= 30)) && (hour < 20 || (hour == 20 && minute <= 30));
|
||||
|
||||
// 获取当前日期(yyyy-MM-dd格式)
|
||||
QString dateStr = currentDateTime.toString("yyyy-MM-dd");
|
||||
|
||||
// 根据时间段返回班次信息
|
||||
if (isDayShift) {
|
||||
return (dateStr + "白班");
|
||||
}
|
||||
else {
|
||||
return (dateStr + "夜班");
|
||||
}
|
||||
}
|
||||
QString getLastProcessCsvName(){
|
||||
// 获取当前时间
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
|
||||
// 获取当前小时和分钟
|
||||
int hour = currentDateTime.time().hour();
|
||||
int minute = currentDateTime.time().minute();
|
||||
|
||||
// 判断是否在白班时间范围(8:30到20:30)
|
||||
bool isDayShift = (hour > 8 || (hour == 8 && minute >= 30)) && (hour < 20 || (hour == 20 && minute <= 30));
|
||||
|
||||
// 获取上一班的日期
|
||||
QDateTime lastShiftDateTime;
|
||||
if (isDayShift) {
|
||||
// 当前是白班,上一班是前一天的夜班
|
||||
lastShiftDateTime = currentDateTime.addDays(-1);
|
||||
}
|
||||
else {
|
||||
// 当前是夜班,上一班是前一天的白班
|
||||
lastShiftDateTime = currentDateTime.addDays(-1);
|
||||
}
|
||||
|
||||
// 获取上一班的日期(yyyy-MM-dd格式)
|
||||
QString dateStr = lastShiftDateTime.toString("yyyy-MM-dd");
|
||||
|
||||
// 根据时间段返回班次信息
|
||||
if (isDayShift) {
|
||||
return (dateStr + "夜班"); // 上一班是夜班
|
||||
}
|
||||
else {
|
||||
return (dateStr + "白班"); // 上一班是白班
|
||||
}
|
||||
}
|
||||
void startAutoExport(int intervalMs = 60000) {
|
||||
m_intervalMs = intervalMs;
|
||||
m_running = true;
|
||||
this->start();
|
||||
}
|
||||
void stopAutoExport() {
|
||||
m_running = false;
|
||||
this->wait();
|
||||
}
|
||||
void exportCsv()
|
||||
{
|
||||
_db.exportTableToCSV(getLastProcessCsvName(), "./csv/", _mutex);
|
||||
_db.exportTableToCSV(getCurrentProcessCsvName(), "./csv/", _mutex);
|
||||
}
|
||||
};
|
||||
|
||||
#pragma once
|
||||
+1
-1
@@ -213,7 +213,7 @@ if(ON)
|
||||
|
||||
set(Qt5_DIR ${PROJECT_ROOT_PATH}/env/qt5/lib/cmake/Qt5)
|
||||
set(QT_DIR ${Qt5_DIR})
|
||||
set(qtlist "Core" "Widgets" "Network" "Gui" "PrintSupport" "Concurrent" "Charts")
|
||||
set(qtlist "Core" "Widgets" "Network" "Gui" "PrintSupport" "Concurrent" "Charts" "Sql")
|
||||
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
|
||||
message("QT_Version :" Qt${QT_VERSION_MAJOR})
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#include "Qt_epWindow.h"
|
||||
#include "qapplication.h"
|
||||
#include <rlib_writeCsv.h>
|
||||
#include <global.h>
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@
|
||||
#include "QtSaveImgSet.h"
|
||||
//缺陷名称设置
|
||||
#include "QtDefectSet.h"
|
||||
|
||||
#pragma execution_character_set("utf-8")
|
||||
|
||||
//struct LogListStruct
|
||||
|
||||
@@ -1,155 +0,0 @@
|
||||
#include <qfile.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <mutex>
|
||||
#include <qdatetime.h>
|
||||
#include <memory>
|
||||
#include <qtextstream.h>
|
||||
class CsvWriter
|
||||
{
|
||||
public:
|
||||
CsvWriter()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
//输入 键 和 数值的键值对,键默认为条码
|
||||
void WriteToCsv(QString key,std::vector<std::pair<QString, QString>> strList)
|
||||
{
|
||||
//查询条码是否存在
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
QTextStream currentCsvStream(currentCsvFile.get());
|
||||
auto it = currentKeys->find(key);
|
||||
if (it != currentKeys->end()) {
|
||||
QList<QString> lines;
|
||||
while (!currentCsvStream.atEnd()) {
|
||||
lines.append(currentCsvStream.readLine());
|
||||
}
|
||||
//lines[it->second]
|
||||
}
|
||||
/*QByteArray qstr;
|
||||
for (int cnt = 0; cnt < strList.size() - 1; cnt++)
|
||||
qstr.append(QByteArray::fromStdString(strList[cnt]) + ",");
|
||||
qstr.append(QByteArray::fromStdString(strList[strList.size() - 1]) + CRLF);*/
|
||||
}
|
||||
void switchCsvFile(std::string path)
|
||||
{
|
||||
//创建文件并检查是否存在
|
||||
|
||||
}
|
||||
void timeCheck()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
std::mutex _mutex;
|
||||
std::shared_ptr<QFile> lastCsvFile;
|
||||
std::shared_ptr<QFile> currentCsvFile;
|
||||
const char* CRLF = "\r\n";
|
||||
QByteArray csvHeaderStr = "";
|
||||
|
||||
std::unordered_map <QString, int> headers;
|
||||
const char* keyName = "条码";
|
||||
std::unordered_map<QString, int>* lastKeys;
|
||||
std::unordered_map<QString, int>* currentKeys;
|
||||
void init()
|
||||
{
|
||||
std::lock_guard<std::mutex> locker(_mutex);
|
||||
addHeader("条码");
|
||||
addHeader("创建时间");
|
||||
addHeader("修改时间");
|
||||
{
|
||||
lastCsvFile = openCsvFile(getLastProcessCsv());
|
||||
QTextStream lastCsvStream(lastCsvFile.get());
|
||||
while (!lastCsvStream.atEnd()) {
|
||||
auto line = lastCsvStream.readLine();
|
||||
auto lineSplit = line.split(",");
|
||||
if (lineSplit.size() > 0){
|
||||
lastKeys->insert({ lineSplit[0],lastKeys->size() + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
currentCsvFile = openCsvFile(getCurrentProcessCsv());
|
||||
QTextStream currentCsvStream(currentCsvFile.get());
|
||||
while (!currentCsvStream.atEnd()) {
|
||||
auto line = currentCsvStream.readLine();
|
||||
auto lineSplit = line.split(",");
|
||||
if (lineSplit.size() > 0) {
|
||||
currentKeys->insert({ lineSplit[0],currentKeys->size() + 1 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
void addHeader(QString header) {
|
||||
headers.insert(std::make_pair(header, headers.size()));
|
||||
if (csvHeaderStr == "")
|
||||
csvHeaderStr.append(header);
|
||||
else
|
||||
csvHeaderStr.append(header + ",");
|
||||
}
|
||||
std::string getCurrentProcessCsv(){
|
||||
// 获取当前时间
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
|
||||
// 获取当前小时和分钟
|
||||
int hour = currentDateTime.time().hour();
|
||||
int minute = currentDateTime.time().minute();
|
||||
|
||||
// 判断是否在白班时间范围(8:30到20:30)
|
||||
bool isDayShift = (hour > 8 || (hour == 8 && minute >= 30)) && (hour < 20 || (hour == 20 && minute <= 30));
|
||||
|
||||
// 获取当前日期(yyyy-MM-dd格式)
|
||||
QString dateStr = currentDateTime.toString("yyyy-MM-dd");
|
||||
|
||||
// 根据时间段返回班次信息
|
||||
if (isDayShift) {
|
||||
return (dateStr + "白班").toStdString();
|
||||
}
|
||||
else {
|
||||
return (dateStr + "夜班").toStdString();
|
||||
}
|
||||
}
|
||||
std::string getLastProcessCsv(){
|
||||
// 获取当前时间
|
||||
QDateTime currentDateTime = QDateTime::currentDateTime();
|
||||
|
||||
// 获取当前小时和分钟
|
||||
int hour = currentDateTime.time().hour();
|
||||
int minute = currentDateTime.time().minute();
|
||||
|
||||
// 判断是否在白班时间范围(8:30到20:30)
|
||||
bool isDayShift = (hour > 8 || (hour == 8 && minute >= 30)) && (hour < 20 || (hour == 20 && minute <= 30));
|
||||
|
||||
// 获取上一班的日期
|
||||
QDateTime lastShiftDateTime;
|
||||
if (isDayShift) {
|
||||
// 当前是白班,上一班是前一天的夜班
|
||||
lastShiftDateTime = currentDateTime.addDays(-1);
|
||||
}
|
||||
else {
|
||||
// 当前是夜班,上一班是前一天的白班
|
||||
lastShiftDateTime = currentDateTime.addDays(-1);
|
||||
}
|
||||
|
||||
// 获取上一班的日期(yyyy-MM-dd格式)
|
||||
QString dateStr = lastShiftDateTime.toString("yyyy-MM-dd");
|
||||
|
||||
// 根据时间段返回班次信息
|
||||
if (isDayShift) {
|
||||
return (dateStr + "夜班").toStdString(); // 上一班是夜班
|
||||
}
|
||||
else {
|
||||
return (dateStr + "白班").toStdString(); // 上一班是白班
|
||||
}
|
||||
}
|
||||
std::shared_ptr<QFile>openCsvFile(std::string path){
|
||||
std::shared_ptr<QFile> CsvFile = std::make_shared<QFile>(QString::fromStdString(path));
|
||||
bool FileExist = CsvFile->exists();
|
||||
CsvFile->open(QIODevice::ReadWrite);
|
||||
if (FileExist == false)
|
||||
CsvFile->write(csvHeaderStr);
|
||||
}
|
||||
};
|
||||
Vendored
+97
-1
@@ -7,4 +7,100 @@
|
||||
#define csvSplitStart "[csvSplitStart]"
|
||||
#define csvSplitEnd "[csvSplitEnd]"
|
||||
#define generalSplit "|"
|
||||
//SAMPLE
|
||||
#include <qbytearray.h>
|
||||
#include <qlist.h>
|
||||
#include <qvariant.h>
|
||||
#include <map>
|
||||
#include <QByteArray>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <map>
|
||||
#include <QVariant>
|
||||
#include <sstream>
|
||||
|
||||
const char* packSplit = "|"; // Separator between fields
|
||||
const char* resultSplitStart = "[resultCmdSplitStart]"; // PLC result start delimiter
|
||||
const char* resultSplitEnd = "[resultCmdSplitEnd]"; // PLC result end delimiter
|
||||
const char* csvChartSplitStart = "[csvChartCmdSplitStart]"; // CSV and chart data start delimiter
|
||||
const char* csvChartSplitEnd = "[csvChartCmdSplitEnd]"; // CSV and chart data end delimiter
|
||||
namespace logicUiTransport
|
||||
{
|
||||
QByteArray encodeAllData(QString SN,QList<QString> plcResult, std::map<QString, QVariant> csvAndChartData)
|
||||
{
|
||||
QByteArray encodedData;
|
||||
|
||||
// Encode plcResult list
|
||||
encodedData.append(resultSplitStart);
|
||||
for (const auto& item : plcResult)
|
||||
{
|
||||
encodedData.append(item.toUtf8() + packSplit);
|
||||
}
|
||||
encodedData.append(resultSplitEnd);
|
||||
|
||||
// Encode csvAndChartData map
|
||||
encodedData.append(csvChartSplitStart);
|
||||
encodedData.append(QString("条码") + packSplit);
|
||||
encodedData.append(SN + packSplit);
|
||||
for (const auto& pair : csvAndChartData)
|
||||
{
|
||||
encodedData.append(pair.first.toUtf8() + packSplit);
|
||||
encodedData.append(pair.second.toString().toUtf8() + packSplit);
|
||||
}
|
||||
encodedData.append(csvChartSplitEnd);
|
||||
|
||||
return encodedData;
|
||||
}
|
||||
|
||||
QByteArrayList decodePlcResult(QByteArray& input)
|
||||
{
|
||||
QByteArrayList plcResultList;
|
||||
|
||||
// Find the data between resultSplitStart and resultSplitEnd
|
||||
int startIndex = input.indexOf(resultSplitStart) + strlen(resultSplitStart);
|
||||
int endIndex = input.indexOf(resultSplitEnd);
|
||||
|
||||
if (startIndex >= 0 && endIndex >= 0 && endIndex > startIndex)
|
||||
{
|
||||
QByteArray plcData = input.mid(startIndex, endIndex - startIndex);
|
||||
QStringList plcList = QString(plcData).split(packSplit, Qt::SkipEmptyParts);
|
||||
|
||||
// Convert each QString to QByteArray and add to the list
|
||||
for (const QString& str : plcList)
|
||||
{
|
||||
plcResultList.append(str.toUtf8());
|
||||
}
|
||||
}
|
||||
|
||||
return plcResultList;
|
||||
}
|
||||
|
||||
std::map<QString, QVariant> decodeCsvAndChartData(QByteArray& input)
|
||||
{
|
||||
std::map<QString, QVariant> csvAndChartData;
|
||||
|
||||
// Find the data between csvChartSplitStart and csvChartSplitEnd
|
||||
int startIndex = input.indexOf(csvChartSplitStart) + strlen(csvChartSplitStart);
|
||||
int endIndex = input.indexOf(csvChartSplitEnd);
|
||||
|
||||
if (startIndex >= 0 && endIndex >= 0 && endIndex > startIndex)
|
||||
{
|
||||
QByteArray csvData = input.mid(startIndex, endIndex - startIndex);
|
||||
QStringList csvList = QString(csvData).split(packSplit, Qt::SkipEmptyParts);
|
||||
|
||||
// Decode key-value pairs
|
||||
for (int i = 0; i < csvList.size(); i += 2)
|
||||
{
|
||||
if (i + 1 < csvList.size())
|
||||
{
|
||||
csvAndChartData[csvList[i]] = QVariant(csvList[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return csvAndChartData;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
#pragma once
|
||||
|
||||
Reference in New Issue
Block a user