mirror of
https://github.com/NanjingForestryUniversity/UPmatchinewood.git
synced 2025-11-08 14:23:59 +00:00
first_version
This commit is contained in:
commit
5d577cb2a3
BIN
._thread.h
Normal file
BIN
._thread.h
Normal file
Binary file not shown.
236
camera.cpp
Normal file
236
camera.cpp
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
#include "camera.h"
|
||||||
|
|
||||||
|
#define FIRST_DEVICE_INDEX 1
|
||||||
|
//#define SETTING_PATH "C:/Program Files/Teledyne DALSA/Sapera/CamFiles/User/202298_first.ccf"
|
||||||
|
#define SETTING_PATH "C:/Program Files/Teledyne DALSA/Sapera/CamFiles/User/abc.ccf"
|
||||||
|
|
||||||
|
extern void onImageDataCallback(SapXferCallbackInfo *pInfo);
|
||||||
|
extern void onImageCorrectCallback(SapXferCallbackInfo *pInfo);
|
||||||
|
|
||||||
|
camera::camera()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool camera::enumDevic(char *serverName)
|
||||||
|
{
|
||||||
|
int devicecount = SapManager::GetServerCount();
|
||||||
|
if(devicecount < 1)
|
||||||
|
{
|
||||||
|
qDebug() << "no device found";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SapManager::GetServerName(FIRST_DEVICE_INDEX, serverName, CORSERVER_MAX_STRLEN);
|
||||||
|
qDebug() << serverName;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool camera::creatObjects(char *serverName)
|
||||||
|
{
|
||||||
|
m_loc = new SapLocation(serverName, 1);
|
||||||
|
m_pAcq = new SapAcquisition(*m_loc, SETTING_PATH);
|
||||||
|
m_buffer = new SapBuffer(1, m_pAcq);
|
||||||
|
// m_trans = new SapAcqToBuf(m_pAcq, m_buffer, onImageDataCallback, NULL);
|
||||||
|
|
||||||
|
if(false == m_pAcq->Create())
|
||||||
|
{
|
||||||
|
destroyObjects();
|
||||||
|
qDebug() << "create pAcq device failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(false == m_buffer->Create())
|
||||||
|
{
|
||||||
|
destroyObjects();
|
||||||
|
qDebug() << "create buff failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(false == m_trans->Create())
|
||||||
|
// {
|
||||||
|
// destroyObjects();
|
||||||
|
// qDebug() << "create transport failed";
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
qDebug() << "create object success";
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void camera::destroyObjects()
|
||||||
|
{
|
||||||
|
if(m_trans && *m_trans)
|
||||||
|
{
|
||||||
|
m_trans->Destroy();
|
||||||
|
qDebug() << "1";
|
||||||
|
}
|
||||||
|
if(c_trans && *c_trans)
|
||||||
|
{
|
||||||
|
c_trans->Destroy();
|
||||||
|
qDebug() << "2";
|
||||||
|
}
|
||||||
|
if(m_buffer && *m_buffer)
|
||||||
|
{
|
||||||
|
m_buffer->Destroy();
|
||||||
|
qDebug() << "3";
|
||||||
|
}
|
||||||
|
if(m_pAcq && *m_pAcq)
|
||||||
|
{
|
||||||
|
m_pAcq->Destroy();
|
||||||
|
qDebug() << "4";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool camera::openCamera()
|
||||||
|
{
|
||||||
|
char serverName[CORSERVER_MAX_STRLEN];
|
||||||
|
if(!enumDevic(serverName))
|
||||||
|
{
|
||||||
|
qDebug() << "enum device failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!creatObjects(serverName))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
qDebug() << "open device success";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void camera::closeCamera()
|
||||||
|
{
|
||||||
|
destroyObjects();
|
||||||
|
if(m_trans)
|
||||||
|
{
|
||||||
|
delete m_trans;
|
||||||
|
qDebug() << "5";
|
||||||
|
}
|
||||||
|
if(c_trans)
|
||||||
|
{
|
||||||
|
delete c_trans;
|
||||||
|
qDebug() << "6";
|
||||||
|
}
|
||||||
|
if(m_buffer)
|
||||||
|
{
|
||||||
|
delete m_buffer;
|
||||||
|
qDebug() << "7";
|
||||||
|
}
|
||||||
|
if(m_pAcq)
|
||||||
|
{
|
||||||
|
delete m_pAcq;
|
||||||
|
qDebug() << "8";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool camera::startCapture()
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
m_trans = new SapAcqToBuf(m_pAcq, m_buffer, onImageDataCallback, NULL);
|
||||||
|
if(false == m_trans->Create())
|
||||||
|
{
|
||||||
|
destroyObjects();
|
||||||
|
if(m_trans && *m_trans)
|
||||||
|
{
|
||||||
|
m_trans->Destroy();
|
||||||
|
}
|
||||||
|
qDebug() << "create transport failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
success = m_trans->Grab();
|
||||||
|
if(success == false)
|
||||||
|
{
|
||||||
|
qDebug() << "grab failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool camera::stopCapture()
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
success = m_trans->Freeze();
|
||||||
|
if(success == false)
|
||||||
|
{
|
||||||
|
qDebug() << "stop capture failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_trans->Wait(5000);
|
||||||
|
if(m_trans && *m_trans)
|
||||||
|
{
|
||||||
|
m_trans->Destroy();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool camera::startCorrect()
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
qDebug() << "start correct";
|
||||||
|
c_trans = new SapAcqToBuf(m_pAcq, m_buffer, onImageCorrectCallback, NULL);
|
||||||
|
if(false == c_trans->Create())
|
||||||
|
{
|
||||||
|
destroyObjects();
|
||||||
|
if(c_trans && *c_trans)
|
||||||
|
{
|
||||||
|
c_trans->Destroy();
|
||||||
|
}
|
||||||
|
qDebug() << "create c_transport failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
qDebug() << "create c_trans";
|
||||||
|
success = c_trans->Grab();
|
||||||
|
if(success == false)
|
||||||
|
{
|
||||||
|
qDebug() << "start correct failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
qDebug() << "c_trans grab";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool camera::stopCorrect()
|
||||||
|
{
|
||||||
|
bool success;
|
||||||
|
success = c_trans->Freeze();
|
||||||
|
if(success == false)
|
||||||
|
{
|
||||||
|
qDebug() << "stop correct failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
c_trans->Wait(5000);
|
||||||
|
|
||||||
|
if(c_trans && *c_trans)
|
||||||
|
{
|
||||||
|
c_trans->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//没用
|
||||||
|
bool camera::interTricapture()
|
||||||
|
{
|
||||||
|
m_pAcq->SetParameter(CORACQ_PRM_INT_LINE_TRIGGER_FREQ, 8, TRUE);//内触发信号频率
|
||||||
|
m_pAcq->SetParameter(CORACQ_PRM_INT_LINE_TRIGGER_ENABLE, TRUE, TRUE);//内触发
|
||||||
|
|
||||||
|
bool success;
|
||||||
|
success = m_trans->Grab();
|
||||||
|
if(success == false)
|
||||||
|
{
|
||||||
|
qDebug() << "inter trigger capture failed";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_trans->Wait(5000);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
48
camera.h
Normal file
48
camera.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#ifndef CAMERA_H
|
||||||
|
#define CAMERA_H
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include "SapClassBasic.h"
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include "thread.h"
|
||||||
|
class camera
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
camera();
|
||||||
|
bool enumDevic(char* serverName);
|
||||||
|
bool creatObjects(char* serverName);
|
||||||
|
void destroyObjects();
|
||||||
|
bool openCamera();
|
||||||
|
void closeCamera();
|
||||||
|
bool startCapture();
|
||||||
|
bool stopCapture();
|
||||||
|
bool interTricapture();
|
||||||
|
|
||||||
|
bool startCorrect();
|
||||||
|
bool stopCorrect();
|
||||||
|
|
||||||
|
bool capture_black_flag = false;
|
||||||
|
bool capture_white_flag = false;
|
||||||
|
bool ret_SCaptrue = false;
|
||||||
|
bool ret_SCorrect = false;
|
||||||
|
cv::Mat white_mat;
|
||||||
|
cv::Mat black_mat;
|
||||||
|
cv::Mat eps;
|
||||||
|
SapTransfer *c_trans;
|
||||||
|
float* white_buf = nullptr;
|
||||||
|
float* black_buf = nullptr;
|
||||||
|
|
||||||
|
SapLocation *m_loc;
|
||||||
|
SapAcquisition *m_pAcq;
|
||||||
|
SapBuffer *m_buffer;
|
||||||
|
SapTransfer *m_trans;
|
||||||
|
|
||||||
|
SapTransfer *l_trans;
|
||||||
|
std::queue<cv::Mat> imgqueue;
|
||||||
|
cv::Mat calibrated_img;
|
||||||
|
int rgb_height;
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CAMERA_H
|
||||||
49
correct.cpp
Normal file
49
correct.cpp
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#include "correct.h"
|
||||||
|
|
||||||
|
correct::correct()
|
||||||
|
{
|
||||||
|
is_corrected = false;
|
||||||
|
correction_ratio_r = 1;
|
||||||
|
correction_ratio_g = 1;
|
||||||
|
correction_ratio_b = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void correct::get_rgb(cv::Mat img)
|
||||||
|
{
|
||||||
|
int b_temp = 0;
|
||||||
|
int g_temp = 0;
|
||||||
|
int r_temp = 0;
|
||||||
|
for(int i=0; i<img.rows; i++)
|
||||||
|
{
|
||||||
|
for(int j=0; j<img.cols; j++)
|
||||||
|
{
|
||||||
|
b_temp += (int)img.at<cv::Vec3b>(i, j)[0];
|
||||||
|
g_temp += (int)img.at<cv::Vec3b>(i, j)[1];
|
||||||
|
r_temp += (int)img.at<cv::Vec3b>(i, j)[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b = b_temp / (img.cols * img.rows);
|
||||||
|
g = g_temp / (img.cols * img.rows);
|
||||||
|
r = r_temp / (img.cols * img.rows);
|
||||||
|
}
|
||||||
|
|
||||||
|
void correct::cal_correction_ratio()
|
||||||
|
{
|
||||||
|
correction_ratio_b = b / b_base;
|
||||||
|
correction_ratio_g = g / g_base;
|
||||||
|
correction_ratio_r = r / r_base;
|
||||||
|
qDebug() << "correction ratio" << correction_ratio_b << correction_ratio_g << correction_ratio_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void correct::correct_img(cv::Mat img)
|
||||||
|
{
|
||||||
|
for(int i=0; i<img.cols; i++)
|
||||||
|
{
|
||||||
|
for(int j=0; j<img.rows; j++)
|
||||||
|
{
|
||||||
|
(img.at<cv::Vec3b>(j, i)[0] * correction_ratio_b) > 255 ? img.at<cv::Vec3b>(j, i)[0] = 255 : img.at<cv::Vec3b>(j, i)[0] *= correction_ratio_b;
|
||||||
|
(img.at<cv::Vec3b>(j, i)[1] * correction_ratio_b) > 255 ? img.at<cv::Vec3b>(j, i)[1] = 255 : img.at<cv::Vec3b>(j, i)[1] *= correction_ratio_b;
|
||||||
|
(img.at<cv::Vec3b>(j, i)[2] * correction_ratio_b) > 255 ? img.at<cv::Vec3b>(j, i)[2] = 255 : img.at<cv::Vec3b>(j, i)[2] *= correction_ratio_b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
correct.h
Normal file
29
correct.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#ifndef CORRECT_H
|
||||||
|
#define CORRECT_H
|
||||||
|
|
||||||
|
#include "opencv2/opencv.hpp"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
class correct
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float correction_ratio;
|
||||||
|
float r;
|
||||||
|
float g;
|
||||||
|
float b;
|
||||||
|
float correction_ratio_r;
|
||||||
|
float correction_ratio_g;
|
||||||
|
float correction_ratio_b;
|
||||||
|
int b_base = 125.0f;
|
||||||
|
int g_base = 125.0f;
|
||||||
|
int r_base = 125.0f;
|
||||||
|
|
||||||
|
public:
|
||||||
|
correct();
|
||||||
|
bool is_corrected;
|
||||||
|
void get_rgb(cv::Mat img);
|
||||||
|
void cal_correction_ratio();
|
||||||
|
void correct_img(cv::Mat img);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CORRECT_H
|
||||||
30
imagewin.cpp
Normal file
30
imagewin.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "imagewin.h"
|
||||||
|
#include "ui_imagewin.h"
|
||||||
|
|
||||||
|
# pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
|
imageWin::imageWin(ListWidgetItemChild *item, QRect rect, QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
ui(new Ui::imageWin)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
|
||||||
|
qApp->installEventFilter(this);
|
||||||
|
this->setGeometry(rect);//设置显示图片窗口的x、y、w、h
|
||||||
|
this->setFixedSize(rect.width(), rect.height());//设置窗口固定大小
|
||||||
|
this->setWindowIcon(item->icon());
|
||||||
|
this->setWindowTitle("查看图片");
|
||||||
|
this->setWindowModality(Qt::ApplicationModal);//阻塞除当前窗体外的其他所有窗体
|
||||||
|
|
||||||
|
//通过QLabel加载item上的图片
|
||||||
|
QLabel *lab = new QLabel(this);
|
||||||
|
lab->setFixedSize(this->width(), this->height());
|
||||||
|
lab->setPixmap(item->icon().pixmap(QSize(this->width(), this->height())).scaled(lab->width(),lab->height()));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
imageWin::~imageWin()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
26
imagewin.h
Normal file
26
imagewin.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#ifndef IMAGEWIN_H
|
||||||
|
#define IMAGEWIN_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QRect>
|
||||||
|
#include <QLabel>
|
||||||
|
#include "relistwidget_item.h"
|
||||||
|
namespace Ui {
|
||||||
|
class imageWin;
|
||||||
|
}
|
||||||
|
|
||||||
|
class imageWin : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit imageWin(ListWidgetItemChild *item, QRect rect, QWidget *parent = 0);
|
||||||
|
~imageWin();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::imageWin *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IMAGEWIN_H
|
||||||
21
imagewin.ui
Normal file
21
imagewin.ui
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<ui version="4.0">
|
||||||
|
<author/>
|
||||||
|
<comment/>
|
||||||
|
<exportmacro/>
|
||||||
|
<class>imageWin</class>
|
||||||
|
<widget class="QWidget" name="imageWin">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<pixmapfunction/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
11
main.cpp
Normal file
11
main.cpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#include "widget.h"
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication a(argc, argv);
|
||||||
|
Widget w;
|
||||||
|
w.show();
|
||||||
|
|
||||||
|
return a.exec();
|
||||||
|
}
|
||||||
23
relistwidget_item.cpp
Normal file
23
relistwidget_item.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "relistwidget_item.h"
|
||||||
|
|
||||||
|
ListWidgetItemChild::ListWidgetItemChild(QListWidget *parent) :
|
||||||
|
QListWidgetItem(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ListWidgetItemChild::~ListWidgetItemChild()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ListWidgetRe::ListWidgetRe(QWidget *parent) :
|
||||||
|
QListWidget(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ListWidgetRe::~ListWidgetRe()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
42
relistwidget_item.h
Normal file
42
relistwidget_item.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#ifndef RELISTWIDGET_ITEM_H
|
||||||
|
#define RELISTWIDGET_ITEM_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <QListView>
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
|
||||||
|
class ListWidgetItemChild : public QListWidgetItem
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ListWidgetItemChild(QListWidget *parent = 0);
|
||||||
|
|
||||||
|
~ListWidgetItemChild();
|
||||||
|
QString LBrightnessValue;
|
||||||
|
QString ARedGreenValue;
|
||||||
|
QString BYellowBlueValue;
|
||||||
|
|
||||||
|
bool operator<(const QListWidgetItem &other) const
|
||||||
|
{
|
||||||
|
int a, b;
|
||||||
|
a = this->text().mid(9,3).toInt();
|
||||||
|
b = other.text().mid(9,3).toInt();
|
||||||
|
return a < b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class ListWidgetRe : public QListWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
friend class ListWidgetItemChild;
|
||||||
|
public:
|
||||||
|
explicit ListWidgetRe(QWidget *parent = nullptr);
|
||||||
|
~ListWidgetRe();
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
// void itemDoubleClicked(ListWidgetItemChild *item);
|
||||||
|
};
|
||||||
|
#endif // RELISTWIDGET_ITEM_H
|
||||||
647
showpic.cpp
Normal file
647
showpic.cpp
Normal file
@ -0,0 +1,647 @@
|
|||||||
|
#include "showpic.h"
|
||||||
|
#include "ui_showpic.h"
|
||||||
|
|
||||||
|
|
||||||
|
# pragma execution_character_set("utf-8")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
void deleteImage(QString folderPath, QString imageName);
|
||||||
|
QString FindImage(QString folderPath, QString imageName);
|
||||||
|
|
||||||
|
extern QString DirPath;
|
||||||
|
//QString DirPath = "D:/picture/524test";
|
||||||
|
|
||||||
|
|
||||||
|
QStringList GetFileNameList(const QString &strDirpath)//该函数的作用是获取一个目录下所有的文件名,并将文件名存储在QStringList中返回。
|
||||||
|
{
|
||||||
|
QDir dir(strDirpath);
|
||||||
|
QFileInfoList Info_list = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
|
||||||
|
QListIterator<QFileInfo> Iterator(Info_list);
|
||||||
|
QStringList strFileNameList;
|
||||||
|
QFileInfo Info;
|
||||||
|
while (Iterator.hasNext())
|
||||||
|
{
|
||||||
|
Info = Iterator.next();
|
||||||
|
if (Info.isFile())
|
||||||
|
{
|
||||||
|
strFileNameList << Info.fileName();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//排序3.28
|
||||||
|
qSort(strFileNameList.begin(), strFileNameList.end(), [](const QString& s1, const QString& s2){
|
||||||
|
return s1.mid(3,2).toInt() < s2.mid(3,2).toInt(); });
|
||||||
|
|
||||||
|
return strFileNameList;
|
||||||
|
}
|
||||||
|
|
||||||
|
showpic::showpic(char* buf1, QWidget *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
//showpic::showpic(QWidget *parent) :
|
||||||
|
// QWidget(parent),
|
||||||
|
ui(new Ui::showpic)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
//切割char数组
|
||||||
|
const char split[] = ",";
|
||||||
|
char* res = strtok(buf1, split);//image_name必须为char[]
|
||||||
|
while (res != NULL)//切割buf,将有用的数据全部在res_split内,可通过res_split.at(i)调用
|
||||||
|
{
|
||||||
|
// qDebug() << "res" << res;
|
||||||
|
res_split.push_back(res);//??
|
||||||
|
res = strtok(NULL, split);//??
|
||||||
|
|
||||||
|
}
|
||||||
|
qDebug() << "res_split.size()" << res_split.size();
|
||||||
|
|
||||||
|
LightPath = DirPath +"/light/";
|
||||||
|
MiddlePath = DirPath +"/Middle/";
|
||||||
|
DarkPath = DirPath +"/dark/";
|
||||||
|
|
||||||
|
QStringList listLight = GetFileNameList(LightPath);//应该是一个全局变量3.28
|
||||||
|
QStringList listMiddle = GetFileNameList(MiddlePath);
|
||||||
|
QStringList listDark = GetFileNameList(DarkPath);
|
||||||
|
|
||||||
|
// QStringList listLight = GetFileNameList("D:/wood_color317/data/2023318/light/");//应该是一个全局变量3.28
|
||||||
|
// QStringList listMiddle = GetFileNameList("D:/wood_color317/data/2023318/middle/");
|
||||||
|
// QStringList listDark = GetFileNameList("D:/wood_color317/data/2023318/dark/");
|
||||||
|
//将90个lab值分三类
|
||||||
|
QVector<char*> Light_lab;
|
||||||
|
QVector<char*> Middle_lab;
|
||||||
|
QVector<char*> Dark_lab;
|
||||||
|
/* for(int i = 0; i < 90; i++)
|
||||||
|
{
|
||||||
|
if(i < 30)
|
||||||
|
{
|
||||||
|
Light_lab.append(res_split.at(i));
|
||||||
|
// qDebug() << Light_lab.at(i) << i;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(i > 29 && i < 60)
|
||||||
|
{
|
||||||
|
Middle_lab.append(res_split.at(i));
|
||||||
|
// qDebug() << Middle_lab.at(i-30) << i;
|
||||||
|
}
|
||||||
|
else if(i > 59 && i < 90)
|
||||||
|
{
|
||||||
|
Dark_lab.append(res_split.at(i));
|
||||||
|
// qDebug() << Dark_lab.at(i-60) << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
for(int i = 0; i < (listLight.size() + listMiddle.size() + listDark.size()); i++)
|
||||||
|
{
|
||||||
|
if(i < listLight.size())
|
||||||
|
{
|
||||||
|
Light_lab.append(res_split.at(i));
|
||||||
|
qDebug() << Light_lab.at(i) << i;
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(i > (listLight.size() - 1) && i < (listLight.size() + listMiddle.size()))
|
||||||
|
{
|
||||||
|
Middle_lab.append(res_split.at(i));
|
||||||
|
qDebug() << Middle_lab.at(i-listLight.size()) << i;
|
||||||
|
}
|
||||||
|
else /*if(i > (listLight.size() + listMiddle.size() - 1) && i < 90)*/
|
||||||
|
{
|
||||||
|
Dark_lab.append(res_split.at(i));
|
||||||
|
qDebug() << Dark_lab.at(i-listLight.size() - listMiddle.size()) << i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
listWidget = new ListWidgetRe(this);
|
||||||
|
listWidget->setViewMode(QListWidget::IconMode);//显示模式
|
||||||
|
listWidget->setIconSize(QSize(400, 90));//设置图片大小
|
||||||
|
listWidget->setSpacing(10);//间距
|
||||||
|
listWidget->setResizeMode(QListView::Adjust);//适应布局调整
|
||||||
|
listWidget->setMovement(QListView::Static);//不能移动
|
||||||
|
|
||||||
|
|
||||||
|
// QString file = "D:/wood_color317/data/2023318/light/";
|
||||||
|
QString file = LightPath;
|
||||||
|
LoadPicture(file, listLight, Light_lab);
|
||||||
|
|
||||||
|
// QListWidgetItem *separate0 = new QListWidgetItem;
|
||||||
|
// separate0->setText("之后为中色");
|
||||||
|
// separate0->setFlags(separate0->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
|
||||||
|
// listWidget->addItem(separate0);
|
||||||
|
|
||||||
|
|
||||||
|
// file = "D:/wood_color317/data/2023318/middle/";
|
||||||
|
file = MiddlePath;
|
||||||
|
LoadPicture(file, listMiddle, Middle_lab);
|
||||||
|
|
||||||
|
// QListWidgetItem *separate1 = new QListWidgetItem;
|
||||||
|
// separate1->setFlags(separate0->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
|
||||||
|
// separate1->setText("之后为深色");
|
||||||
|
// listWidget->addItem(separate1);
|
||||||
|
|
||||||
|
// file = "D:/wood_color317/data/2023318/dark/";
|
||||||
|
file = DarkPath;
|
||||||
|
LoadPicture(file, listDark, Dark_lab);
|
||||||
|
|
||||||
|
listWidget->sortItems();
|
||||||
|
listWidget->setSelectionMode(QAbstractItemView::MultiSelection);//设置多选模式
|
||||||
|
QVBoxLayout* VBox = new QVBoxLayout;
|
||||||
|
QHBoxLayout* HBox = new QHBoxLayout;
|
||||||
|
ui->pushButton->setFixedSize(140,70);
|
||||||
|
ui->pushButton_2->setFixedSize(140,70);
|
||||||
|
ui->pushButton_3->setFixedSize(140,70);
|
||||||
|
ui->pushButton_light->setFixedSize(140,70);
|
||||||
|
ui->pushButton_middle->setFixedSize(140,70);
|
||||||
|
ui->pushButton_dark->setFixedSize(140,70);
|
||||||
|
|
||||||
|
|
||||||
|
HBox->addWidget(ui->pushButton);
|
||||||
|
HBox->addWidget(ui->pushButton_2);
|
||||||
|
HBox->addWidget(ui->pushButton_3);
|
||||||
|
HBox->addWidget(ui->pushButton_light);
|
||||||
|
HBox->addWidget(ui->pushButton_middle);
|
||||||
|
HBox->addWidget(ui->pushButton_dark);
|
||||||
|
|
||||||
|
|
||||||
|
VBox->addWidget(listWidget);
|
||||||
|
VBox->addLayout(HBox);
|
||||||
|
|
||||||
|
this->setLayout(VBox);
|
||||||
|
|
||||||
|
connect(listWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(enlargeImage(QListWidgetItem*)));
|
||||||
|
|
||||||
|
qDebug() << "showpic ready";
|
||||||
|
|
||||||
|
emit PictureReady();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
showpic::~showpic()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void showpic::enlargeImage(QListWidgetItem *item)
|
||||||
|
{
|
||||||
|
|
||||||
|
QRect rect = this->geometry();//获取当前窗口坐标及大小 x、y、w、h
|
||||||
|
// static_cast<ListWidgetItemChild*>(listWidget->itemWidget(item));
|
||||||
|
ListWidgetItemChild *item0 = static_cast<ListWidgetItemChild *>(item);
|
||||||
|
//通过自定义的窗口显示图片
|
||||||
|
// imageWin *showImageWidget = new imageWin(item , QRect(rect.x(), rect.y()+rect.y()*1/4, rect.width(), rect.height()*2/3));
|
||||||
|
imageWin *showImageWidget = new imageWin(item0 , QRect(rect.x(), rect.y()+rect.y()*1/4, rect.width(), rect.height()*1.7/3));
|
||||||
|
showImageWidget->show();
|
||||||
|
|
||||||
|
//显示条目名称
|
||||||
|
qDebug() << item0->text();
|
||||||
|
QString item_name = item0->text();
|
||||||
|
if(item_name.at(4) != '.')
|
||||||
|
{
|
||||||
|
QString a = item_name.at(3);
|
||||||
|
a.append(item_name.at(4));
|
||||||
|
qDebug() << "a" << a.toInt();
|
||||||
|
// int b = a.toInt();
|
||||||
|
int L = item0->LBrightnessValue.toInt();
|
||||||
|
int A = item0->ARedGreenValue.toInt();
|
||||||
|
int B = item0->BYellowBlueValue.toInt();
|
||||||
|
qDebug() << "LAB" << L << A << B;
|
||||||
|
//显示色块
|
||||||
|
cv::Mat mat = cv::Mat(100, 100, CV_8UC3, cv::Scalar(L, A, B));
|
||||||
|
cv::cvtColor(mat, mat, cv::COLOR_Lab2BGR);
|
||||||
|
cv::imshow("sekuai", mat);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "--";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
//rgb00.png175136163QQ
|
||||||
|
//拼图片路径,并添加到imageItem,再添加到listWidget
|
||||||
|
void showpic::LoadPicture(QString file, QStringList list, QVector<char*> lab)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < list.size(); i++)
|
||||||
|
{
|
||||||
|
qDebug() << lab.at(i) << i;
|
||||||
|
QString LAB = lab.at(i);
|
||||||
|
QString tmp = file + list.at(i);//拼出图片绝对路径
|
||||||
|
|
||||||
|
ListWidgetItemChild *imageItem = new ListWidgetItemChild;
|
||||||
|
imageItem->LBrightnessValue =LAB.mid(0,3);
|
||||||
|
imageItem->ARedGreenValue = LAB.mid(3,3);
|
||||||
|
imageItem->BYellowBlueValue = LAB.mid(6,3);
|
||||||
|
|
||||||
|
imageItem->setIcon(QIcon(tmp));
|
||||||
|
imageItem->setText(list.at(i) + LAB.mid(0,3) + LAB.mid(9,2));
|
||||||
|
// qDebug() << "luminance1" << lab.at(i) << i;
|
||||||
|
if(LAB.mid(9,1) == LAB.mid(10,1))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
imageItem->setTextColor(Qt::red);
|
||||||
|
}
|
||||||
|
imageItem->setSizeHint(QSize(400, 120));
|
||||||
|
listWidget->addItem(imageItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
//rgb00.png000
|
||||||
|
//bool showpic::CompareItem(ListWidgetItemChild *item1, ListWidgetItemChild *item2)
|
||||||
|
//{
|
||||||
|
// int luminance1 = item1->text().mid(9,3).toInt();
|
||||||
|
// qDebug() << "luminance1" << luminance1;
|
||||||
|
// int luminance2 = item2->text().mid(9,3).toInt();
|
||||||
|
// qDebug() << "luminance2" << luminance2;
|
||||||
|
|
||||||
|
// return luminance1 < luminance2;
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void showpic::on_pushButton_clicked()
|
||||||
|
{
|
||||||
|
// 获取选中的item
|
||||||
|
QList<QListWidgetItem*> selectedItems = listWidget->selectedItems();
|
||||||
|
// QListWidgetItem *selectedItem = listWidget->currentItem();
|
||||||
|
if (selectedItems.size() != 1) {
|
||||||
|
// 如果选中的item数量不等于2,则弹出提示框并返回
|
||||||
|
QMessageBox::warning(this, "Error", "请至少选择一张图片");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//并从文件夹中删除
|
||||||
|
QListWidgetItem* item1 = selectedItems[0];
|
||||||
|
QString DelPicName = item1->text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
deleteImage(DirPath, DelPicName);
|
||||||
|
|
||||||
|
// 如果有选中的item,则删除它
|
||||||
|
if (item1 != nullptr) {
|
||||||
|
delete item1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void showpic::on_pushButton_2_clicked()
|
||||||
|
{
|
||||||
|
|
||||||
|
// 获取选中的两个item
|
||||||
|
QList<QListWidgetItem*> selectedItems = listWidget->selectedItems();
|
||||||
|
if (selectedItems.size() != 2) {
|
||||||
|
// 如果选中的item数量不等于2,则弹出提示框并返回
|
||||||
|
QMessageBox::warning(this, "Error", "请选中2张图片进行操作:先选的图片插入到后选的后面");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QListWidgetItem* item1 = selectedItems[0];
|
||||||
|
QListWidgetItem* item2 = selectedItems[1];
|
||||||
|
|
||||||
|
// 获取它们在listWidget中的位置
|
||||||
|
int index1 = listWidget->row(item1);
|
||||||
|
int index2 = listWidget->row(item2);
|
||||||
|
qDebug() << "index1" << index1;
|
||||||
|
qDebug() << "index2" << index2;
|
||||||
|
|
||||||
|
// 交换它们的位置,!!!!!!!!!有点问题
|
||||||
|
listWidget->takeItem(index1);
|
||||||
|
listWidget->takeItem(index2);
|
||||||
|
listWidget->insertItem(index1, item2);
|
||||||
|
listWidget->insertItem(index2, item1);
|
||||||
|
|
||||||
|
index1 = listWidget->row(item1);
|
||||||
|
index2 = listWidget->row(item2);
|
||||||
|
qDebug() << "index1new" << index1;
|
||||||
|
qDebug() << "index2new" << index2;
|
||||||
|
|
||||||
|
// 取消选中状态
|
||||||
|
item1->setSelected(false);
|
||||||
|
item2->setSelected(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showpic::on_pushButton_3_clicked()
|
||||||
|
{
|
||||||
|
if(listWidget->currentItem() == nullptr)
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, "Error", "请点击一个图片进行操作");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QListWidgetItem *selectedItem = listWidget->currentItem();
|
||||||
|
|
||||||
|
|
||||||
|
QString PicNamePath = FindImage(DirPath, selectedItem->text().mid(0, 9));//
|
||||||
|
// sprintf(PicNamePath, PicNamePath);
|
||||||
|
cv::Mat Pic = cv::imread(PicNamePath.toLatin1().data());// .toLatin1().data(): string转char*
|
||||||
|
|
||||||
|
QInputDialog *inputDialog_item=new QInputDialog(this);
|
||||||
|
QStringList list;
|
||||||
|
list<<"浅色"<<"中色"<<"深色";
|
||||||
|
bool getItem;
|
||||||
|
QString season = inputDialog_item->getItem(this,"选择文件夹","文件夹类别",list,0,false,&getItem);
|
||||||
|
if(getItem)
|
||||||
|
{
|
||||||
|
if("浅色" == season)
|
||||||
|
{
|
||||||
|
QString RePicName = LightPath + selectedItem->text().mid(0,9);
|
||||||
|
// PicImg.save(RePicName, "PNG", -1);
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = selectedItem->text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
deleteImage(MiddlePath, DelPicName);
|
||||||
|
deleteImage(DarkPath, DelPicName);
|
||||||
|
|
||||||
|
if (selectedItem != nullptr) {
|
||||||
|
delete selectedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if("中色" == season)
|
||||||
|
{
|
||||||
|
QString RePicName = MiddlePath + selectedItem->text().mid(0,9);
|
||||||
|
// PicImg.save(RePicName, "PNG", -1);
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = selectedItem->text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
deleteImage(LightPath, DelPicName);
|
||||||
|
deleteImage(DarkPath, DelPicName);
|
||||||
|
|
||||||
|
if (selectedItem != nullptr) {
|
||||||
|
delete selectedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if("深色" == season)
|
||||||
|
{
|
||||||
|
QString RePicName = DarkPath + selectedItem->text().mid(0,9);
|
||||||
|
// PicImg.save(RePicName, "PNG", -1);
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = selectedItem->text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
deleteImage(LightPath, DelPicName);
|
||||||
|
deleteImage(MiddlePath, DelPicName);
|
||||||
|
|
||||||
|
if (selectedItem != nullptr) {
|
||||||
|
delete selectedItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//按键,多选移动rgb00.png000QQ
|
||||||
|
void showpic::on_pushButton_light_clicked()
|
||||||
|
{
|
||||||
|
QList<QListWidgetItem*> selectedItems = listWidget->selectedItems();
|
||||||
|
|
||||||
|
int Numbers = selectedItems.size();
|
||||||
|
QListWidgetItem* Item = new QListWidgetItem[Numbers];
|
||||||
|
for(int i = 0; i < Numbers; i++)
|
||||||
|
{
|
||||||
|
// qDebug() <<
|
||||||
|
Item[i] = *selectedItems[i];
|
||||||
|
if(Item[i].text().mid(12, 1) == 'Q')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(Item[i].text().mid(12, 1) == 'S')
|
||||||
|
{
|
||||||
|
// QString PicNamePath = FindImage("D:/2023/wooden/2023318/", Item[i].text().mid(0,9));
|
||||||
|
QString PicNamePath = FindImage(DirPath, Item[i].text().mid(0,9));
|
||||||
|
cv::Mat Pic = cv::imread(PicNamePath.toLatin1().data());
|
||||||
|
|
||||||
|
// QString RePicName = "D:/2023/wooden/2023318/light/" + Item[i].text().mid(0,9);
|
||||||
|
QString RePicName = LightPath + Item[i].text().mid(0,9);
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = Item[i].text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
// deleteImage("D:/2023/wooden/2023318/dark/", DelPicName);
|
||||||
|
deleteImage(DarkPath, DelPicName);
|
||||||
|
if (selectedItems[i] != nullptr) {
|
||||||
|
delete selectedItems[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Item[i].text().mid(12, 1) == 'Z')
|
||||||
|
{
|
||||||
|
// QString PicNamePath = FindImage("D:/2023/wooden/2023318/", Item[i].text().mid(0,9));
|
||||||
|
QString PicNamePath = FindImage(DirPath, Item[i].text().mid(0,9));
|
||||||
|
cv::Mat Pic = cv::imread(PicNamePath.toLatin1().data());
|
||||||
|
|
||||||
|
// QString RePicName = "D:/2023/wooden/2023318/light/" + Item[i].text().mid(0,9);
|
||||||
|
QString RePicName = LightPath + Item[i].text().mid(0,9);
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = Item[i].text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
// deleteImage("D:/2023/wooden/2023318/middle/", DelPicName);
|
||||||
|
deleteImage(MiddlePath, DelPicName);
|
||||||
|
|
||||||
|
if (selectedItems[i] != nullptr) {
|
||||||
|
delete selectedItems[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showpic::on_pushButton_middle_clicked()
|
||||||
|
{
|
||||||
|
QList<QListWidgetItem*> selectedItems = listWidget->selectedItems();
|
||||||
|
|
||||||
|
int Numbers = selectedItems.size();
|
||||||
|
QListWidgetItem* Item = new QListWidgetItem[Numbers];
|
||||||
|
for(int i = 0; i < Numbers; i++)
|
||||||
|
{
|
||||||
|
Item[i] = *selectedItems[i];
|
||||||
|
if(Item[i].text().mid(12, 1) == 'Z')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(Item[i].text().mid(12, 1) == 'S')
|
||||||
|
{
|
||||||
|
// QString PicNamePath = FindImage("D:/2023/wooden/2023318/", Item[i].text().mid(0,9));
|
||||||
|
QString PicNamePath = FindImage(DirPath, Item[i].text().mid(0,9));
|
||||||
|
|
||||||
|
cv::Mat Pic = cv::imread(PicNamePath.toLatin1().data());
|
||||||
|
|
||||||
|
// QString RePicName = "D:/2023/wooden/2023318/middle/" + Item[i].text().mid(0,9);
|
||||||
|
QString RePicName = MiddlePath + Item[i].text().mid(0,9);
|
||||||
|
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = Item[i].text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
// deleteImage("D:/2023/wooden/2023318/dark/", DelPicName);
|
||||||
|
deleteImage(DarkPath, DelPicName);
|
||||||
|
|
||||||
|
if (selectedItems[i] != nullptr) {
|
||||||
|
delete selectedItems[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Item[i].text().mid(12, 1) == 'Q')
|
||||||
|
{
|
||||||
|
// QString PicNamePath = FindImage("D:/2023/wooden/2023318/", Item[i].text().mid(0,9));
|
||||||
|
QString PicNamePath = FindImage(DirPath, Item[i].text().mid(0,9));
|
||||||
|
cv::Mat Pic = cv::imread(PicNamePath.toLatin1().data());
|
||||||
|
|
||||||
|
// QString RePicName = "D:/2023/wooden/2023318/middle/" + Item[i].text().mid(0,9);
|
||||||
|
QString RePicName = MiddlePath + Item[i].text().mid(0,9);
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = Item[i].text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
// deleteImage("D:/2023/wooden/2023318/light/", DelPicName);
|
||||||
|
deleteImage(LightPath, DelPicName);
|
||||||
|
|
||||||
|
|
||||||
|
if (selectedItems[i] != nullptr) {
|
||||||
|
delete selectedItems[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showpic::on_pushButton_dark_clicked()
|
||||||
|
{
|
||||||
|
QList<QListWidgetItem*> selectedItems = listWidget->selectedItems();
|
||||||
|
|
||||||
|
int Numbers = selectedItems.size();
|
||||||
|
QListWidgetItem* Item = new QListWidgetItem[Numbers];
|
||||||
|
for(int i = 0; i < Numbers; i++)
|
||||||
|
{
|
||||||
|
Item[i] = *selectedItems[i];
|
||||||
|
if(Item[i].text().mid(12, 1) == 'S')
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(Item[i].text().mid(12, 1) == 'Q')
|
||||||
|
{
|
||||||
|
// QString PicNamePath = FindImage("D:/2023/wooden/2023318/", Item[i].text().mid(0,9));
|
||||||
|
QString PicNamePath = FindImage(DirPath, Item[i].text().mid(0,9));
|
||||||
|
|
||||||
|
cv::Mat Pic = cv::imread(PicNamePath.toLatin1().data());
|
||||||
|
|
||||||
|
// QString RePicName = "D:/2023/wooden/2023318/dark/" + Item[i].text().mid(0,9);
|
||||||
|
QString RePicName = DarkPath + Item[i].text().mid(0,9);
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = Item[i].text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
// deleteImage("D:/2023/wooden/2023318/light/", DelPicName);
|
||||||
|
deleteImage(LightPath, DelPicName);
|
||||||
|
|
||||||
|
if (selectedItems[i] != nullptr) {
|
||||||
|
delete selectedItems[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(Item[i].text().mid(12, 1) == 'Z')
|
||||||
|
{
|
||||||
|
// QString PicNamePath = FindImage("D:/2023/wooden/2023318/", Item[i].text().mid(0,9));
|
||||||
|
QString PicNamePath = FindImage(DirPath, Item[i].text().mid(0,9));
|
||||||
|
cv::Mat Pic = cv::imread(PicNamePath.toLatin1().data());
|
||||||
|
|
||||||
|
// QString RePicName = "D:/2023/wooden/2023318/dark/" + Item[i].text().mid(0,9);
|
||||||
|
QString RePicName = DarkPath + Item[i].text().mid(0,9);
|
||||||
|
|
||||||
|
cv::imwrite(RePicName.toLatin1().data(), Pic);
|
||||||
|
|
||||||
|
//调用删除图片函数
|
||||||
|
QString DelPicName = Item[i].text().mid(0,9);
|
||||||
|
qDebug() << "DelPicName" << DelPicName;
|
||||||
|
// deleteImage("D:/2023/wooden/2023318/middle/", DelPicName);
|
||||||
|
deleteImage(MiddlePath, DelPicName);
|
||||||
|
|
||||||
|
|
||||||
|
if (selectedItems[i] != nullptr) {
|
||||||
|
delete selectedItems[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//从文件夹中删除图片
|
||||||
|
void deleteImage(QString folderPath, QString imageName) {
|
||||||
|
QDir folder(folderPath);
|
||||||
|
QFileInfoList entries = folder.entryInfoList(QDir::AllEntries | QDir::NoDotAndDotDot);
|
||||||
|
|
||||||
|
for (const QFileInfo &entry : entries) {
|
||||||
|
if (entry.isFile() && entry.fileName() == imageName) {
|
||||||
|
// 找到了指定图片,删除它
|
||||||
|
qDebug() << "entry.absoluteFilePath()" << entry.absoluteFilePath();
|
||||||
|
if (QFile::remove(entry.absoluteFilePath())) {
|
||||||
|
QMessageBox::information(nullptr, "Success", "Image deleted successfully");
|
||||||
|
} else {
|
||||||
|
// QMessageBox::warning(nullptr, "Error", "Failed to delete image");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (entry.isDir()) {
|
||||||
|
// 递归进入子文件夹查找图片
|
||||||
|
deleteImage(entry.absoluteFilePath(), imageName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果遍历完当前文件夹和子文件夹都没有找到指定图片,则弹出失败提示框
|
||||||
|
// QMessageBox::warning(nullptr, "Error", "Failed to find image");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FindImage(QString folderPath, QString imageName)
|
||||||
|
{
|
||||||
|
|
||||||
|
QDir folderDir(folderPath);
|
||||||
|
|
||||||
|
// 获取文件夹中的所有文件和文件夹
|
||||||
|
QStringList entries = folderDir.entryList();
|
||||||
|
|
||||||
|
// 遍历文件夹中的所有文件和文件夹
|
||||||
|
foreach(QString entry, entries)
|
||||||
|
{
|
||||||
|
QString entryPath = folderPath + "/" + entry;
|
||||||
|
|
||||||
|
// 如果是子文件夹,进入子文件夹查找图片
|
||||||
|
if(QFileInfo(entryPath).isDir())
|
||||||
|
{
|
||||||
|
QDir subFolderDir(entryPath);
|
||||||
|
QStringList subEntries = subFolderDir.entryList();
|
||||||
|
|
||||||
|
// 遍历子文件夹中的所有文件
|
||||||
|
foreach(QString subEntry, subEntries)
|
||||||
|
{
|
||||||
|
QString subEntryPath = entryPath + "/" + subEntry;
|
||||||
|
|
||||||
|
// 如果是目标图片,返回其绝对路径
|
||||||
|
if(subEntry == imageName)
|
||||||
|
{
|
||||||
|
QString imagePath = QFileInfo(subEntryPath).absoluteFilePath();
|
||||||
|
return imagePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 如果是目标图片,返回其绝对路径
|
||||||
|
else if(entry == imageName)
|
||||||
|
{
|
||||||
|
QString imagePath = QFileInfo(entryPath).absoluteFilePath();
|
||||||
|
return imagePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果未找到目标图片,返回空字符串
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
69
showpic.h
Normal file
69
showpic.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#ifndef SHOWPIC_H
|
||||||
|
#define SHOWPIC_H
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
#include <opencv2/core/core.hpp>
|
||||||
|
#include <opencv2/highgui/highgui.hpp>
|
||||||
|
#include "opencv2/imgproc/types_c.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QMessageBox>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include "relistwidget_item.h"
|
||||||
|
#include "imagewin.h"
|
||||||
|
#include <QVBoxlayout>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class showpic;
|
||||||
|
}
|
||||||
|
|
||||||
|
class showpic : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit showpic(char*, QWidget *parent = 0);
|
||||||
|
// explicit showpic(QWidget *parent = 0);
|
||||||
|
~showpic();
|
||||||
|
QVector<char*> res_split;//存储分割后的字符串
|
||||||
|
ListWidgetRe *listWidget;
|
||||||
|
|
||||||
|
QString LightPath;
|
||||||
|
QString MiddlePath;
|
||||||
|
QString DarkPath;
|
||||||
|
void LoadPicture(QString file, QStringList list, QVector<char*>);
|
||||||
|
// bool CompareItem(ListWidgetItemChild* item1, ListWidgetItemChild* item2);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void enlargeImage(QListWidgetItem *item);//放大图片
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void PictureReady();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_pushButton_clicked();
|
||||||
|
|
||||||
|
void on_pushButton_2_clicked();
|
||||||
|
|
||||||
|
void on_pushButton_3_clicked();
|
||||||
|
|
||||||
|
void on_pushButton_light_clicked();
|
||||||
|
|
||||||
|
void on_pushButton_middle_clicked();
|
||||||
|
|
||||||
|
void on_pushButton_dark_clicked();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::showpic *ui;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHOWPIC_H
|
||||||
127
showpic.ui
Normal file
127
showpic.ui
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>showpic</class>
|
||||||
|
<widget class="QWidget" name="showpic">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1126</width>
|
||||||
|
<height>668</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QPushButton" name="pushButton">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>60</x>
|
||||||
|
<y>540</y>
|
||||||
|
<width>141</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>19</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>删除</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="pushButton_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>290</x>
|
||||||
|
<y>540</y>
|
||||||
|
<width>181</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>19</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>移动</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="pushButton_3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>530</x>
|
||||||
|
<y>540</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>14</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>改变所属分类</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="pushButton_light">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>700</x>
|
||||||
|
<y>540</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>14</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>移入浅色</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="pushButton_middle">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>850</x>
|
||||||
|
<y>540</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>14</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>移入中色</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="pushButton_dark">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>990</x>
|
||||||
|
<y>540</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>14</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>移入深色</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
233
src/modbus-data.c
Normal file
233
src/modbus-data.c
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
# include <stdint.h>
|
||||||
|
#else
|
||||||
|
# include "stdint.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# include <winsock2.h>
|
||||||
|
#else
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#include <config.h>
|
||||||
|
|
||||||
|
#include "modbus.h"
|
||||||
|
|
||||||
|
#if defined(HAVE_BYTESWAP_H)
|
||||||
|
# include <byteswap.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__APPLE__)
|
||||||
|
# include <libkern/OSByteOrder.h>
|
||||||
|
# define bswap_16 OSSwapInt16
|
||||||
|
# define bswap_32 OSSwapInt32
|
||||||
|
# define bswap_64 OSSwapInt64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__ * 10)
|
||||||
|
# if GCC_VERSION >= 430
|
||||||
|
// Since GCC >= 4.30, GCC provides __builtin_bswapXX() alternatives so we switch to them
|
||||||
|
# undef bswap_32
|
||||||
|
# define bswap_32 __builtin_bswap32
|
||||||
|
# endif
|
||||||
|
# if GCC_VERSION >= 480
|
||||||
|
# undef bswap_16
|
||||||
|
# define bswap_16 __builtin_bswap16
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||||
|
# define bswap_32 _byteswap_ulong
|
||||||
|
# define bswap_16 _byteswap_ushort
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(bswap_16)
|
||||||
|
# warning "Fallback on C functions for bswap_16"
|
||||||
|
static inline uint16_t bswap_16(uint16_t x)
|
||||||
|
{
|
||||||
|
return (x >> 8) | (x << 8);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(bswap_32)
|
||||||
|
# warning "Fallback on C functions for bswap_32"
|
||||||
|
static inline uint32_t bswap_32(uint32_t x)
|
||||||
|
{
|
||||||
|
return (bswap_16(x & 0xffff) << 16) | (bswap_16(x >> 16));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Sets many bits from a single byte value (all 8 bits of the byte value are
|
||||||
|
set) */
|
||||||
|
void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i < 8; i++) {
|
||||||
|
dest[idx+i] = (value & (1 << i)) ? 1 : 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sets many bits from a table of bytes (only the bits between idx and
|
||||||
|
idx + nb_bits are set) */
|
||||||
|
void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,
|
||||||
|
const uint8_t *tab_byte)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
int shift = 0;
|
||||||
|
|
||||||
|
for (i = idx; i < idx + nb_bits; i++) {
|
||||||
|
dest[i] = tab_byte[(i - idx) / 8] & (1 << shift) ? 1 : 0;
|
||||||
|
/* gcc doesn't like: shift = (++shift) % 8; */
|
||||||
|
shift++;
|
||||||
|
shift %= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Gets the byte value from many bits.
|
||||||
|
To obtain a full byte, set nb_bits to 8. */
|
||||||
|
uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx,
|
||||||
|
unsigned int nb_bits)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
uint8_t value = 0;
|
||||||
|
|
||||||
|
if (nb_bits > 8) {
|
||||||
|
/* Assert is ignored if NDEBUG is set */
|
||||||
|
assert(nb_bits < 8);
|
||||||
|
nb_bits = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i=0; i < nb_bits; i++) {
|
||||||
|
value |= (src[idx+i] << i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a float from 4 bytes (Modbus) without any conversion (ABCD) */
|
||||||
|
float modbus_get_float_abcd(const uint16_t *src)
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
i = ntohl(((uint32_t)src[0] << 16) + src[1]);
|
||||||
|
memcpy(&f, &i, sizeof(float));
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a float from 4 bytes (Modbus) in inversed format (DCBA) */
|
||||||
|
float modbus_get_float_dcba(const uint16_t *src)
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
i = ntohl(bswap_32((((uint32_t)src[0]) << 16) + src[1]));
|
||||||
|
memcpy(&f, &i, sizeof(float));
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a float from 4 bytes (Modbus) with swapped bytes (BADC) */
|
||||||
|
float modbus_get_float_badc(const uint16_t *src)
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
i = ntohl((uint32_t)(bswap_16(src[0]) << 16) + bswap_16(src[1]));
|
||||||
|
memcpy(&f, &i, sizeof(float));
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get a float from 4 bytes (Modbus) with swapped words (CDAB) */
|
||||||
|
float modbus_get_float_cdab(const uint16_t *src)
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
i = ntohl((((uint32_t)src[1]) << 16) + src[0]);
|
||||||
|
memcpy(&f, &i, sizeof(float));
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEPRECATED - Get a float from 4 bytes in sort of Modbus format */
|
||||||
|
float modbus_get_float(const uint16_t *src)
|
||||||
|
{
|
||||||
|
float f;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
i = (((uint32_t)src[1]) << 16) + src[0];
|
||||||
|
memcpy(&f, &i, sizeof(float));
|
||||||
|
|
||||||
|
return f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a float to 4 bytes for Modbus w/o any conversion (ABCD) */
|
||||||
|
void modbus_set_float_abcd(float f, uint16_t *dest)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
memcpy(&i, &f, sizeof(uint32_t));
|
||||||
|
i = htonl(i);
|
||||||
|
dest[0] = (uint16_t)(i >> 16);
|
||||||
|
dest[1] = (uint16_t)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a float to 4 bytes for Modbus with byte and word swap conversion (DCBA) */
|
||||||
|
void modbus_set_float_dcba(float f, uint16_t *dest)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
memcpy(&i, &f, sizeof(uint32_t));
|
||||||
|
i = bswap_32(htonl(i));
|
||||||
|
dest[0] = (uint16_t)(i >> 16);
|
||||||
|
dest[1] = (uint16_t)i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a float to 4 bytes for Modbus with byte swap conversion (BADC) */
|
||||||
|
void modbus_set_float_badc(float f, uint16_t *dest)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
memcpy(&i, &f, sizeof(uint32_t));
|
||||||
|
i = htonl(i);
|
||||||
|
dest[0] = (uint16_t)bswap_16(i >> 16);
|
||||||
|
dest[1] = (uint16_t)bswap_16(i & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set a float to 4 bytes for Modbus with word swap conversion (CDAB) */
|
||||||
|
void modbus_set_float_cdab(float f, uint16_t *dest)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
memcpy(&i, &f, sizeof(uint32_t));
|
||||||
|
i = htonl(i);
|
||||||
|
dest[0] = (uint16_t)i;
|
||||||
|
dest[1] = (uint16_t)(i >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* DEPRECATED - Set a float to 4 bytes in a sort of Modbus format! */
|
||||||
|
void modbus_set_float(float f, uint16_t *dest)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
memcpy(&i, &f, sizeof(uint32_t));
|
||||||
|
dest[0] = (uint16_t)i;
|
||||||
|
dest[1] = (uint16_t)(i >> 16);
|
||||||
|
}
|
||||||
116
src/modbus-private.h
Normal file
116
src/modbus-private.h
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2010-2012 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODBUS_PRIVATE_H
|
||||||
|
#define MODBUS_PRIVATE_H
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
# include <stdint.h>
|
||||||
|
# include <sys/time.h>
|
||||||
|
#else
|
||||||
|
# include "stdint.h"
|
||||||
|
# include <time.h>
|
||||||
|
typedef int ssize_t;
|
||||||
|
#endif
|
||||||
|
#include <sys/types.h>
|
||||||
|
//#include <config.h>
|
||||||
|
|
||||||
|
#include "modbus.h"
|
||||||
|
|
||||||
|
MODBUS_BEGIN_DECLS
|
||||||
|
|
||||||
|
/* It's not really the minimal length (the real one is report slave ID
|
||||||
|
* in RTU (4 bytes)) but it's a convenient size to use in RTU or TCP
|
||||||
|
* communications to read many values or write a single one.
|
||||||
|
* Maximum between :
|
||||||
|
* - HEADER_LENGTH_TCP (7) + function (1) + address (2) + number (2)
|
||||||
|
* - HEADER_LENGTH_RTU (1) + function (1) + address (2) + number (2) + CRC (2)
|
||||||
|
*/
|
||||||
|
#define _MIN_REQ_LENGTH 12
|
||||||
|
|
||||||
|
#define _REPORT_SLAVE_ID 180
|
||||||
|
|
||||||
|
#define _MODBUS_EXCEPTION_RSP_LENGTH 5
|
||||||
|
|
||||||
|
/* Timeouts in microsecond (0.5 s) */
|
||||||
|
#define _RESPONSE_TIMEOUT 500000
|
||||||
|
#define _BYTE_TIMEOUT 500000
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
_MODBUS_BACKEND_TYPE_RTU=0,
|
||||||
|
_MODBUS_BACKEND_TYPE_TCP
|
||||||
|
} modbus_backend_type_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ---------- Request Indication ----------
|
||||||
|
* | Client | ---------------------->| Server |
|
||||||
|
* ---------- Confirmation Response ----------
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/* Request message on the server side */
|
||||||
|
MSG_INDICATION,
|
||||||
|
/* Request message on the client side */
|
||||||
|
MSG_CONFIRMATION
|
||||||
|
} msg_type_t;
|
||||||
|
|
||||||
|
/* This structure reduces the number of params in functions and so
|
||||||
|
* optimizes the speed of execution (~ 37%). */
|
||||||
|
typedef struct _sft {
|
||||||
|
int slave;
|
||||||
|
int function;
|
||||||
|
int t_id;
|
||||||
|
} sft_t;
|
||||||
|
|
||||||
|
typedef struct _modbus_backend {
|
||||||
|
unsigned int backend_type;
|
||||||
|
unsigned int header_length;
|
||||||
|
unsigned int checksum_length;
|
||||||
|
unsigned int max_adu_length;
|
||||||
|
int (*set_slave) (modbus_t *ctx, int slave);
|
||||||
|
int (*build_request_basis) (modbus_t *ctx, int function, int addr,
|
||||||
|
int nb, uint8_t *req);
|
||||||
|
int (*build_response_basis) (sft_t *sft, uint8_t *rsp);
|
||||||
|
int (*prepare_response_tid) (const uint8_t *req, int *req_length);
|
||||||
|
int (*send_msg_pre) (uint8_t *req, int req_length);
|
||||||
|
ssize_t (*send) (modbus_t *ctx, const uint8_t *req, int req_length);
|
||||||
|
int (*receive) (modbus_t *ctx, uint8_t *req);
|
||||||
|
ssize_t (*recv) (modbus_t *ctx, uint8_t *rsp, int rsp_length);
|
||||||
|
int (*check_integrity) (modbus_t *ctx, uint8_t *msg,
|
||||||
|
const int msg_length);
|
||||||
|
int (*pre_check_confirmation) (modbus_t *ctx, const uint8_t *req,
|
||||||
|
const uint8_t *rsp, int rsp_length);
|
||||||
|
int (*connect) (modbus_t *ctx);
|
||||||
|
void (*close) (modbus_t *ctx);
|
||||||
|
int (*flush) (modbus_t *ctx);
|
||||||
|
int (*select) (modbus_t *ctx, fd_set *rset, struct timeval *tv, int msg_length);
|
||||||
|
void (*free) (modbus_t *ctx);
|
||||||
|
} modbus_backend_t;
|
||||||
|
|
||||||
|
struct _modbus {
|
||||||
|
/* Slave address */
|
||||||
|
int slave;
|
||||||
|
/* Socket or file descriptor */
|
||||||
|
int s;
|
||||||
|
int debug;
|
||||||
|
int error_recovery;
|
||||||
|
struct timeval response_timeout;
|
||||||
|
struct timeval byte_timeout;
|
||||||
|
struct timeval indication_timeout;
|
||||||
|
const modbus_backend_t *backend;
|
||||||
|
void *backend_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
void _modbus_init_common(modbus_t *ctx);
|
||||||
|
void _error_print(modbus_t *ctx, const char *context);
|
||||||
|
int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type);
|
||||||
|
|
||||||
|
#ifndef HAVE_STRLCPY
|
||||||
|
size_t strlcpy(char *dest, const char *src, size_t dest_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MODBUS_END_DECLS
|
||||||
|
|
||||||
|
#endif /* MODBUS_PRIVATE_H */
|
||||||
76
src/modbus-rtu-private.h
Normal file
76
src/modbus-rtu-private.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODBUS_RTU_PRIVATE_H
|
||||||
|
#define MODBUS_RTU_PRIVATE_H
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
|
#include "stdint.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <termios.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _MODBUS_RTU_HEADER_LENGTH 1
|
||||||
|
#define _MODBUS_RTU_PRESET_REQ_LENGTH 6
|
||||||
|
#define _MODBUS_RTU_PRESET_RSP_LENGTH 2
|
||||||
|
|
||||||
|
#define _MODBUS_RTU_CHECKSUM_LENGTH 2
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#if !defined(ENOTSUP)
|
||||||
|
#define ENOTSUP WSAEOPNOTSUPP
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* WIN32: struct containing serial handle and a receive buffer */
|
||||||
|
#define PY_BUF_SIZE 512
|
||||||
|
struct win32_ser {
|
||||||
|
/* File handle */
|
||||||
|
HANDLE fd;
|
||||||
|
/* Receive buffer */
|
||||||
|
uint8_t buf[PY_BUF_SIZE];
|
||||||
|
/* Received chars */
|
||||||
|
DWORD n_bytes;
|
||||||
|
};
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
typedef struct _modbus_rtu {
|
||||||
|
/* Device: "/dev/ttyS0", "/dev/ttyUSB0" or "/dev/tty.USA19*" on Mac OS X. */
|
||||||
|
char *device;
|
||||||
|
/* Bauds: 9600, 19200, 57600, 115200, etc */
|
||||||
|
int baud;
|
||||||
|
/* Data bit */
|
||||||
|
uint8_t data_bit;
|
||||||
|
/* Stop bit */
|
||||||
|
uint8_t stop_bit;
|
||||||
|
/* Parity: 'N', 'O', 'E' */
|
||||||
|
char parity;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
struct win32_ser w_ser;
|
||||||
|
DCB old_dcb;
|
||||||
|
#else
|
||||||
|
/* Save old termios settings */
|
||||||
|
struct termios old_tios;
|
||||||
|
#endif
|
||||||
|
#if HAVE_DECL_TIOCSRS485
|
||||||
|
int serial_mode;
|
||||||
|
#endif
|
||||||
|
#if HAVE_DECL_TIOCM_RTS
|
||||||
|
int rts;
|
||||||
|
int rts_delay;
|
||||||
|
int onebyte_time;
|
||||||
|
void (*set_rts) (modbus_t *ctx, int on);
|
||||||
|
#endif
|
||||||
|
/* To handle many slaves on the same link */
|
||||||
|
int confirmation_to_ignore;
|
||||||
|
} modbus_rtu_t;
|
||||||
|
|
||||||
|
#endif /* MODBUS_RTU_PRIVATE_H */
|
||||||
1299
src/modbus-rtu.c
Normal file
1299
src/modbus-rtu.c
Normal file
File diff suppressed because it is too large
Load Diff
42
src/modbus-rtu.h
Normal file
42
src/modbus-rtu.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODBUS_RTU_H
|
||||||
|
#define MODBUS_RTU_H
|
||||||
|
|
||||||
|
#include "modbus.h"
|
||||||
|
|
||||||
|
MODBUS_BEGIN_DECLS
|
||||||
|
|
||||||
|
/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5
|
||||||
|
* RS232 / RS485 ADU = 253 bytes + slave (1 byte) + CRC (2 bytes) = 256 bytes
|
||||||
|
*/
|
||||||
|
#define MODBUS_RTU_MAX_ADU_LENGTH 256
|
||||||
|
|
||||||
|
MODBUS_API modbus_t* modbus_new_rtu(const char *device, int baud, char parity,
|
||||||
|
int data_bit, int stop_bit);
|
||||||
|
|
||||||
|
#define MODBUS_RTU_RS232 0
|
||||||
|
#define MODBUS_RTU_RS485 1
|
||||||
|
|
||||||
|
MODBUS_API int modbus_rtu_set_serial_mode(modbus_t *ctx, int mode);
|
||||||
|
MODBUS_API int modbus_rtu_get_serial_mode(modbus_t *ctx);
|
||||||
|
|
||||||
|
#define MODBUS_RTU_RTS_NONE 0
|
||||||
|
#define MODBUS_RTU_RTS_UP 1
|
||||||
|
#define MODBUS_RTU_RTS_DOWN 2
|
||||||
|
|
||||||
|
MODBUS_API int modbus_rtu_set_rts(modbus_t *ctx, int mode);
|
||||||
|
MODBUS_API int modbus_rtu_get_rts(modbus_t *ctx);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_rtu_set_custom_rts(modbus_t *ctx, void (*set_rts) (modbus_t *ctx, int on));
|
||||||
|
|
||||||
|
MODBUS_API int modbus_rtu_set_rts_delay(modbus_t *ctx, int us);
|
||||||
|
MODBUS_API int modbus_rtu_get_rts_delay(modbus_t *ctx);
|
||||||
|
|
||||||
|
MODBUS_END_DECLS
|
||||||
|
|
||||||
|
#endif /* MODBUS_RTU_H */
|
||||||
44
src/modbus-tcp-private.h
Normal file
44
src/modbus-tcp-private.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2001-2011 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODBUS_TCP_PRIVATE_H
|
||||||
|
#define MODBUS_TCP_PRIVATE_H
|
||||||
|
|
||||||
|
#define _MODBUS_TCP_HEADER_LENGTH 7
|
||||||
|
#define _MODBUS_TCP_PRESET_REQ_LENGTH 12
|
||||||
|
#define _MODBUS_TCP_PRESET_RSP_LENGTH 8
|
||||||
|
|
||||||
|
#define _MODBUS_TCP_CHECKSUM_LENGTH 0
|
||||||
|
|
||||||
|
/* In both structures, the transaction ID must be placed on first position
|
||||||
|
to have a quick access not dependant of the TCP backend */
|
||||||
|
typedef struct _modbus_tcp {
|
||||||
|
/* Extract from MODBUS Messaging on TCP/IP Implementation Guide V1.0b
|
||||||
|
(page 23/46):
|
||||||
|
The transaction identifier is used to associate the future response
|
||||||
|
with the request. This identifier is unique on each TCP connection. */
|
||||||
|
uint16_t t_id;
|
||||||
|
/* TCP port */
|
||||||
|
int port;
|
||||||
|
/* IP address */
|
||||||
|
char ip[16];
|
||||||
|
} modbus_tcp_t;
|
||||||
|
|
||||||
|
#define _MODBUS_TCP_PI_NODE_LENGTH 1025
|
||||||
|
#define _MODBUS_TCP_PI_SERVICE_LENGTH 32
|
||||||
|
|
||||||
|
typedef struct _modbus_tcp_pi {
|
||||||
|
/* Transaction ID */
|
||||||
|
uint16_t t_id;
|
||||||
|
/* TCP port */
|
||||||
|
int port;
|
||||||
|
/* Node */
|
||||||
|
char node[_MODBUS_TCP_PI_NODE_LENGTH];
|
||||||
|
/* Service */
|
||||||
|
char service[_MODBUS_TCP_PI_SERVICE_LENGTH];
|
||||||
|
} modbus_tcp_pi_t;
|
||||||
|
|
||||||
|
#endif /* MODBUS_TCP_PRIVATE_H */
|
||||||
929
src/modbus-tcp.c
Normal file
929
src/modbus-tcp.c
Normal file
@ -0,0 +1,929 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2001-2013 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
# define OS_WIN32
|
||||||
|
/* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later.
|
||||||
|
* minwg32 headers check WINVER before allowing the use of these */
|
||||||
|
# ifndef WINVER
|
||||||
|
# define WINVER 0x0501
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <signal.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
/* Already set in modbus-tcp.h but it seems order matters in VS2005 */
|
||||||
|
# include <winsock2.h>
|
||||||
|
# include <ws2tcpip.h>
|
||||||
|
# define SHUT_RDWR 2
|
||||||
|
# define close closesocket
|
||||||
|
#else
|
||||||
|
# include <sys/socket.h>
|
||||||
|
# include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#if defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD__ < 5)
|
||||||
|
# define OS_BSD
|
||||||
|
# include <netinet/in_systm.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
# include <netinet/in.h>
|
||||||
|
# include <netinet/ip.h>
|
||||||
|
# include <netinet/tcp.h>
|
||||||
|
# include <arpa/inet.h>
|
||||||
|
# include <netdb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(MSG_NOSIGNAL)
|
||||||
|
#define MSG_NOSIGNAL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_AIX) && !defined(MSG_DONTWAIT)
|
||||||
|
#define MSG_DONTWAIT MSG_NONBLOCK
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "modbus-private.h"
|
||||||
|
|
||||||
|
#include "modbus-tcp.h"
|
||||||
|
#include "modbus-tcp-private.h"
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
static int _modbus_tcp_init_win32(void)
|
||||||
|
{
|
||||||
|
/* Initialise Windows Socket API */
|
||||||
|
WSADATA wsaData;
|
||||||
|
|
||||||
|
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
|
||||||
|
fprintf(stderr, "WSAStartup() returned error code %d\n",
|
||||||
|
(unsigned int)GetLastError());
|
||||||
|
errno = EIO;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int _modbus_set_slave(modbus_t *ctx, int slave)
|
||||||
|
{
|
||||||
|
/* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
|
||||||
|
if (slave >= 0 && slave <= 247) {
|
||||||
|
ctx->slave = slave;
|
||||||
|
} else if (slave == MODBUS_TCP_SLAVE) {
|
||||||
|
/* The special value MODBUS_TCP_SLAVE (0xFF) can be used in TCP mode to
|
||||||
|
* restore the default value. */
|
||||||
|
ctx->slave = slave;
|
||||||
|
} else {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Builds a TCP request header */
|
||||||
|
static int _modbus_tcp_build_request_basis(modbus_t *ctx, int function,
|
||||||
|
int addr, int nb,
|
||||||
|
uint8_t *req)
|
||||||
|
{
|
||||||
|
modbus_tcp_t *ctx_tcp = ctx->backend_data;
|
||||||
|
|
||||||
|
/* Increase transaction ID */
|
||||||
|
if (ctx_tcp->t_id < UINT16_MAX)
|
||||||
|
ctx_tcp->t_id++;
|
||||||
|
else
|
||||||
|
ctx_tcp->t_id = 0;
|
||||||
|
req[0] = ctx_tcp->t_id >> 8;
|
||||||
|
req[1] = ctx_tcp->t_id & 0x00ff;
|
||||||
|
|
||||||
|
/* Protocol Modbus */
|
||||||
|
req[2] = 0;
|
||||||
|
req[3] = 0;
|
||||||
|
|
||||||
|
/* Length will be defined later by set_req_length_tcp at offsets 4
|
||||||
|
and 5 */
|
||||||
|
|
||||||
|
req[6] = ctx->slave;
|
||||||
|
req[7] = function;
|
||||||
|
req[8] = addr >> 8;
|
||||||
|
req[9] = addr & 0x00ff;
|
||||||
|
req[10] = nb >> 8;
|
||||||
|
req[11] = nb & 0x00ff;
|
||||||
|
|
||||||
|
return _MODBUS_TCP_PRESET_REQ_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Builds a TCP response header */
|
||||||
|
static int _modbus_tcp_build_response_basis(sft_t *sft, uint8_t *rsp)
|
||||||
|
{
|
||||||
|
/* Extract from MODBUS Messaging on TCP/IP Implementation
|
||||||
|
Guide V1.0b (page 23/46):
|
||||||
|
The transaction identifier is used to associate the future
|
||||||
|
response with the request. */
|
||||||
|
rsp[0] = sft->t_id >> 8;
|
||||||
|
rsp[1] = sft->t_id & 0x00ff;
|
||||||
|
|
||||||
|
/* Protocol Modbus */
|
||||||
|
rsp[2] = 0;
|
||||||
|
rsp[3] = 0;
|
||||||
|
|
||||||
|
/* Length will be set later by send_msg (4 and 5) */
|
||||||
|
|
||||||
|
/* The slave ID is copied from the indication */
|
||||||
|
rsp[6] = sft->slave;
|
||||||
|
rsp[7] = sft->function;
|
||||||
|
|
||||||
|
return _MODBUS_TCP_PRESET_RSP_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int _modbus_tcp_prepare_response_tid(const uint8_t *req, int *req_length)
|
||||||
|
{
|
||||||
|
return (req[0] << 8) + req[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _modbus_tcp_send_msg_pre(uint8_t *req, int req_length)
|
||||||
|
{
|
||||||
|
/* Substract the header length to the message length */
|
||||||
|
int mbap_length = req_length - 6;
|
||||||
|
|
||||||
|
req[4] = mbap_length >> 8;
|
||||||
|
req[5] = mbap_length & 0x00FF;
|
||||||
|
|
||||||
|
return req_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t _modbus_tcp_send(modbus_t *ctx, const uint8_t *req, int req_length)
|
||||||
|
{
|
||||||
|
/* MSG_NOSIGNAL
|
||||||
|
Requests not to send SIGPIPE on errors on stream oriented
|
||||||
|
sockets when the other end breaks the connection. The EPIPE
|
||||||
|
error is still returned. */
|
||||||
|
return send(ctx->s, (const char *)req, req_length, MSG_NOSIGNAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _modbus_tcp_receive(modbus_t *ctx, uint8_t *req) {
|
||||||
|
return _modbus_receive_msg(ctx, req, MSG_INDICATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t _modbus_tcp_recv(modbus_t *ctx, uint8_t *rsp, int rsp_length) {
|
||||||
|
return recv(ctx->s, (char *)rsp, rsp_length, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _modbus_tcp_check_integrity(modbus_t *ctx, uint8_t *msg, const int msg_length)
|
||||||
|
{
|
||||||
|
return msg_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _modbus_tcp_pre_check_confirmation(modbus_t *ctx, const uint8_t *req,
|
||||||
|
const uint8_t *rsp, int rsp_length)
|
||||||
|
{
|
||||||
|
/* Check transaction ID */
|
||||||
|
if (req[0] != rsp[0] || req[1] != rsp[1]) {
|
||||||
|
if (ctx->debug) {
|
||||||
|
fprintf(stderr, "Invalid transaction ID received 0x%X (not 0x%X)\n",
|
||||||
|
(rsp[0] << 8) + rsp[1], (req[0] << 8) + req[1]);
|
||||||
|
}
|
||||||
|
errno = EMBBADDATA;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check protocol ID */
|
||||||
|
if (rsp[2] != 0x0 && rsp[3] != 0x0) {
|
||||||
|
if (ctx->debug) {
|
||||||
|
fprintf(stderr, "Invalid protocol ID received 0x%X (not 0x0)\n",
|
||||||
|
(rsp[2] << 8) + rsp[3]);
|
||||||
|
}
|
||||||
|
errno = EMBBADDATA;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _modbus_tcp_set_ipv4_options(int s)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int option;
|
||||||
|
|
||||||
|
/* Set the TCP no delay flag */
|
||||||
|
/* SOL_TCP = IPPROTO_TCP */
|
||||||
|
option = 1;
|
||||||
|
rc = setsockopt(s, IPPROTO_TCP, TCP_NODELAY,
|
||||||
|
(const void *)&option, sizeof(int));
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the OS does not offer SOCK_NONBLOCK, fall back to setting FIONBIO to
|
||||||
|
* make sockets non-blocking */
|
||||||
|
/* Do not care about the return value, this is optional */
|
||||||
|
#if !defined(SOCK_NONBLOCK) && defined(FIONBIO)
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
{
|
||||||
|
/* Setting FIONBIO expects an unsigned long according to MSDN */
|
||||||
|
u_long loption = 1;
|
||||||
|
ioctlsocket(s, FIONBIO, &loption);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
option = 1;
|
||||||
|
ioctl(s, FIONBIO, &option);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef OS_WIN32
|
||||||
|
/**
|
||||||
|
* Cygwin defines IPTOS_LOWDELAY but can't handle that flag so it's
|
||||||
|
* necessary to workaround that problem.
|
||||||
|
**/
|
||||||
|
/* Set the IP low delay option */
|
||||||
|
option = IPTOS_LOWDELAY;
|
||||||
|
rc = setsockopt(s, IPPROTO_IP, IP_TOS,
|
||||||
|
(const void *)&option, sizeof(int));
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen,
|
||||||
|
const struct timeval *ro_tv)
|
||||||
|
{
|
||||||
|
int rc = connect(sockfd, addr, addrlen);
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
int wsaError = 0;
|
||||||
|
if (rc == -1) {
|
||||||
|
wsaError = WSAGetLastError();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wsaError == WSAEWOULDBLOCK || wsaError == WSAEINPROGRESS) {
|
||||||
|
#else
|
||||||
|
if (rc == -1 && errno == EINPROGRESS) {
|
||||||
|
#endif
|
||||||
|
fd_set wset;
|
||||||
|
int optval;
|
||||||
|
socklen_t optlen = sizeof(optval);
|
||||||
|
struct timeval tv = *ro_tv;
|
||||||
|
|
||||||
|
/* Wait to be available in writing */
|
||||||
|
FD_ZERO(&wset);
|
||||||
|
FD_SET(sockfd, &wset);
|
||||||
|
rc = select(sockfd + 1, NULL, &wset, NULL, &tv);
|
||||||
|
if (rc <= 0) {
|
||||||
|
/* Timeout or fail */
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The connection is established if SO_ERROR and optval are set to 0 */
|
||||||
|
rc = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void *)&optval, &optlen);
|
||||||
|
if (rc == 0 && optval == 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
errno = ECONNREFUSED;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Establishes a modbus TCP connection with a Modbus server. */
|
||||||
|
static int _modbus_tcp_connect(modbus_t *ctx)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
/* Specialized version of sockaddr for Internet socket address (same size) */
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
modbus_tcp_t *ctx_tcp = ctx->backend_data;
|
||||||
|
int flags = SOCK_STREAM;
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
if (_modbus_tcp_init_win32() == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
|
flags |= SOCK_CLOEXEC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SOCK_NONBLOCK
|
||||||
|
flags |= SOCK_NONBLOCK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctx->s = socket(PF_INET, flags, 0);
|
||||||
|
if (ctx->s == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = _modbus_tcp_set_ipv4_options(ctx->s);
|
||||||
|
if (rc == -1) {
|
||||||
|
close(ctx->s);
|
||||||
|
ctx->s = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->debug) {
|
||||||
|
printf("Connecting to %s:%d\n", ctx_tcp->ip, ctx_tcp->port);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(ctx_tcp->port);
|
||||||
|
addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
|
||||||
|
rc = _connect(ctx->s, (struct sockaddr *)&addr, sizeof(addr), &ctx->response_timeout);
|
||||||
|
if (rc == -1) {
|
||||||
|
close(ctx->s);
|
||||||
|
ctx->s = -1;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Establishes a modbus TCP PI connection with a Modbus server. */
|
||||||
|
static int _modbus_tcp_pi_connect(modbus_t *ctx)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct addrinfo *ai_list;
|
||||||
|
struct addrinfo *ai_ptr;
|
||||||
|
struct addrinfo ai_hints;
|
||||||
|
modbus_tcp_pi_t *ctx_tcp_pi = ctx->backend_data;
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
if (_modbus_tcp_init_win32() == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memset(&ai_hints, 0, sizeof(ai_hints));
|
||||||
|
#ifdef AI_ADDRCONFIG
|
||||||
|
ai_hints.ai_flags |= AI_ADDRCONFIG;
|
||||||
|
#endif
|
||||||
|
ai_hints.ai_family = AF_UNSPEC;
|
||||||
|
ai_hints.ai_socktype = SOCK_STREAM;
|
||||||
|
ai_hints.ai_addr = NULL;
|
||||||
|
ai_hints.ai_canonname = NULL;
|
||||||
|
ai_hints.ai_next = NULL;
|
||||||
|
|
||||||
|
ai_list = NULL;
|
||||||
|
rc = getaddrinfo(ctx_tcp_pi->node, ctx_tcp_pi->service,
|
||||||
|
&ai_hints, &ai_list);
|
||||||
|
if (rc != 0) {
|
||||||
|
if (ctx->debug) {
|
||||||
|
fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc));
|
||||||
|
}
|
||||||
|
errno = ECONNREFUSED;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
|
||||||
|
int flags = ai_ptr->ai_socktype;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
|
flags |= SOCK_CLOEXEC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SOCK_NONBLOCK
|
||||||
|
flags |= SOCK_NONBLOCK;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol);
|
||||||
|
if (s < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ai_ptr->ai_family == AF_INET)
|
||||||
|
_modbus_tcp_set_ipv4_options(s);
|
||||||
|
|
||||||
|
if (ctx->debug) {
|
||||||
|
printf("Connecting to [%s]:%s\n", ctx_tcp_pi->node, ctx_tcp_pi->service);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = _connect(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen, &ctx->response_timeout);
|
||||||
|
if (rc == -1) {
|
||||||
|
close(s);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->s = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
freeaddrinfo(ai_list);
|
||||||
|
|
||||||
|
if (ctx->s < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Closes the network connection and socket in TCP mode */
|
||||||
|
static void _modbus_tcp_close(modbus_t *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->s != -1) {
|
||||||
|
shutdown(ctx->s, SHUT_RDWR);
|
||||||
|
close(ctx->s);
|
||||||
|
ctx->s = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _modbus_tcp_flush(modbus_t *ctx)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
int rc_sum = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* Extract the garbage from the socket */
|
||||||
|
char devnull[MODBUS_TCP_MAX_ADU_LENGTH];
|
||||||
|
#ifndef OS_WIN32
|
||||||
|
rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT);
|
||||||
|
#else
|
||||||
|
/* On Win32, it's a bit more complicated to not wait */
|
||||||
|
fd_set rset;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
FD_ZERO(&rset);
|
||||||
|
FD_SET(ctx->s, &rset);
|
||||||
|
rc = select(ctx->s+1, &rset, NULL, NULL, &tv);
|
||||||
|
if (rc == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rc == 1) {
|
||||||
|
/* There is data to flush */
|
||||||
|
rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (rc > 0) {
|
||||||
|
rc_sum += rc;
|
||||||
|
}
|
||||||
|
} while (rc == MODBUS_TCP_MAX_ADU_LENGTH);
|
||||||
|
|
||||||
|
return rc_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Listens for any request from one or many modbus masters in TCP */
|
||||||
|
int modbus_tcp_listen(modbus_t *ctx, int nb_connection)
|
||||||
|
{
|
||||||
|
int new_s;
|
||||||
|
int enable;
|
||||||
|
int flags;
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
modbus_tcp_t *ctx_tcp;
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx_tcp = ctx->backend_data;
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
if (_modbus_tcp_init_win32() == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
flags = SOCK_STREAM;
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
|
flags |= SOCK_CLOEXEC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
new_s = socket(PF_INET, flags, IPPROTO_TCP);
|
||||||
|
if (new_s == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
enable = 1;
|
||||||
|
if (setsockopt(new_s, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(char *)&enable, sizeof(enable)) == -1) {
|
||||||
|
close(new_s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&addr, 0, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
/* If the modbus port is < to 1024, we need the setuid root. */
|
||||||
|
addr.sin_port = htons(ctx_tcp->port);
|
||||||
|
if (ctx_tcp->ip[0] == '0') {
|
||||||
|
/* Listen any addresses */
|
||||||
|
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
} else {
|
||||||
|
/* Listen only specified IP address */
|
||||||
|
addr.sin_addr.s_addr = inet_addr(ctx_tcp->ip);
|
||||||
|
}
|
||||||
|
if (bind(new_s, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
|
||||||
|
close(new_s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (listen(new_s, nb_connection) == -1) {
|
||||||
|
close(new_s);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct addrinfo *ai_list;
|
||||||
|
struct addrinfo *ai_ptr;
|
||||||
|
struct addrinfo ai_hints;
|
||||||
|
const char *node;
|
||||||
|
const char *service;
|
||||||
|
int new_s;
|
||||||
|
modbus_tcp_pi_t *ctx_tcp_pi;
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx_tcp_pi = ctx->backend_data;
|
||||||
|
|
||||||
|
#ifdef OS_WIN32
|
||||||
|
if (_modbus_tcp_init_win32() == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ctx_tcp_pi->node[0] == 0) {
|
||||||
|
node = NULL; /* == any */
|
||||||
|
} else {
|
||||||
|
node = ctx_tcp_pi->node;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx_tcp_pi->service[0] == 0) {
|
||||||
|
service = "502";
|
||||||
|
} else {
|
||||||
|
service = ctx_tcp_pi->service;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&ai_hints, 0, sizeof (ai_hints));
|
||||||
|
/* If node is not NULL, than the AI_PASSIVE flag is ignored. */
|
||||||
|
ai_hints.ai_flags |= AI_PASSIVE;
|
||||||
|
#ifdef AI_ADDRCONFIG
|
||||||
|
ai_hints.ai_flags |= AI_ADDRCONFIG;
|
||||||
|
#endif
|
||||||
|
ai_hints.ai_family = AF_UNSPEC;
|
||||||
|
ai_hints.ai_socktype = SOCK_STREAM;
|
||||||
|
ai_hints.ai_addr = NULL;
|
||||||
|
ai_hints.ai_canonname = NULL;
|
||||||
|
ai_hints.ai_next = NULL;
|
||||||
|
|
||||||
|
ai_list = NULL;
|
||||||
|
rc = getaddrinfo(node, service, &ai_hints, &ai_list);
|
||||||
|
if (rc != 0) {
|
||||||
|
if (ctx->debug) {
|
||||||
|
fprintf(stderr, "Error returned by getaddrinfo: %s\n", gai_strerror(rc));
|
||||||
|
}
|
||||||
|
errno = ECONNREFUSED;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_s = -1;
|
||||||
|
for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) {
|
||||||
|
int flags = ai_ptr->ai_socktype;
|
||||||
|
int s;
|
||||||
|
|
||||||
|
#ifdef SOCK_CLOEXEC
|
||||||
|
flags |= SOCK_CLOEXEC;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
s = socket(ai_ptr->ai_family, flags, ai_ptr->ai_protocol);
|
||||||
|
if (s < 0) {
|
||||||
|
if (ctx->debug) {
|
||||||
|
perror("socket");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
int enable = 1;
|
||||||
|
rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
|
||||||
|
(void *)&enable, sizeof (enable));
|
||||||
|
if (rc != 0) {
|
||||||
|
close(s);
|
||||||
|
if (ctx->debug) {
|
||||||
|
perror("setsockopt");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = bind(s, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
|
||||||
|
if (rc != 0) {
|
||||||
|
close(s);
|
||||||
|
if (ctx->debug) {
|
||||||
|
perror("bind");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = listen(s, nb_connection);
|
||||||
|
if (rc != 0) {
|
||||||
|
close(s);
|
||||||
|
if (ctx->debug) {
|
||||||
|
perror("listen");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
new_s = s;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
freeaddrinfo(ai_list);
|
||||||
|
|
||||||
|
if (new_s < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modbus_tcp_accept(modbus_t *ctx, int *s)
|
||||||
|
{
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
socklen_t addrlen;
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrlen = sizeof(addr);
|
||||||
|
#ifdef HAVE_ACCEPT4
|
||||||
|
/* Inherit socket flags and use accept4 call */
|
||||||
|
ctx->s = accept4(*s, (struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);
|
||||||
|
#else
|
||||||
|
ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ctx->s == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->debug) {
|
||||||
|
printf("The client connection from %s is accepted\n",
|
||||||
|
inet_ntoa(addr.sin_addr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx->s;
|
||||||
|
}
|
||||||
|
|
||||||
|
int modbus_tcp_pi_accept(modbus_t *ctx, int *s)
|
||||||
|
{
|
||||||
|
struct sockaddr_storage addr;
|
||||||
|
socklen_t addrlen;
|
||||||
|
|
||||||
|
if (ctx == NULL) {
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
addrlen = sizeof(addr);
|
||||||
|
#ifdef HAVE_ACCEPT4
|
||||||
|
/* Inherit socket flags and use accept4 call */
|
||||||
|
ctx->s = accept4(*s, (struct sockaddr *)&addr, &addrlen, SOCK_CLOEXEC);
|
||||||
|
#else
|
||||||
|
ctx->s = accept(*s, (struct sockaddr *)&addr, &addrlen);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ctx->s == -1) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx->debug) {
|
||||||
|
printf("The client connection is accepted.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx->s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read)
|
||||||
|
{
|
||||||
|
int s_rc;
|
||||||
|
while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
if (ctx->debug) {
|
||||||
|
fprintf(stderr, "A non blocked signal was caught\n");
|
||||||
|
}
|
||||||
|
/* Necessary after an error */
|
||||||
|
FD_ZERO(rset);
|
||||||
|
FD_SET(ctx->s, rset);
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_rc == 0) {
|
||||||
|
errno = ETIMEDOUT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _modbus_tcp_free(modbus_t *ctx) {
|
||||||
|
free(ctx->backend_data);
|
||||||
|
free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
const modbus_backend_t _modbus_tcp_backend = {
|
||||||
|
_MODBUS_BACKEND_TYPE_TCP,
|
||||||
|
_MODBUS_TCP_HEADER_LENGTH,
|
||||||
|
_MODBUS_TCP_CHECKSUM_LENGTH,
|
||||||
|
MODBUS_TCP_MAX_ADU_LENGTH,
|
||||||
|
_modbus_set_slave,
|
||||||
|
_modbus_tcp_build_request_basis,
|
||||||
|
_modbus_tcp_build_response_basis,
|
||||||
|
_modbus_tcp_prepare_response_tid,
|
||||||
|
_modbus_tcp_send_msg_pre,
|
||||||
|
_modbus_tcp_send,
|
||||||
|
_modbus_tcp_receive,
|
||||||
|
_modbus_tcp_recv,
|
||||||
|
_modbus_tcp_check_integrity,
|
||||||
|
_modbus_tcp_pre_check_confirmation,
|
||||||
|
_modbus_tcp_connect,
|
||||||
|
_modbus_tcp_close,
|
||||||
|
_modbus_tcp_flush,
|
||||||
|
_modbus_tcp_select,
|
||||||
|
_modbus_tcp_free
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const modbus_backend_t _modbus_tcp_pi_backend = {
|
||||||
|
_MODBUS_BACKEND_TYPE_TCP,
|
||||||
|
_MODBUS_TCP_HEADER_LENGTH,
|
||||||
|
_MODBUS_TCP_CHECKSUM_LENGTH,
|
||||||
|
MODBUS_TCP_MAX_ADU_LENGTH,
|
||||||
|
_modbus_set_slave,
|
||||||
|
_modbus_tcp_build_request_basis,
|
||||||
|
_modbus_tcp_build_response_basis,
|
||||||
|
_modbus_tcp_prepare_response_tid,
|
||||||
|
_modbus_tcp_send_msg_pre,
|
||||||
|
_modbus_tcp_send,
|
||||||
|
_modbus_tcp_receive,
|
||||||
|
_modbus_tcp_recv,
|
||||||
|
_modbus_tcp_check_integrity,
|
||||||
|
_modbus_tcp_pre_check_confirmation,
|
||||||
|
_modbus_tcp_pi_connect,
|
||||||
|
_modbus_tcp_close,
|
||||||
|
_modbus_tcp_flush,
|
||||||
|
_modbus_tcp_select,
|
||||||
|
_modbus_tcp_free
|
||||||
|
};
|
||||||
|
|
||||||
|
modbus_t* modbus_new_tcp(const char *ip, int port)
|
||||||
|
{
|
||||||
|
modbus_t *ctx;
|
||||||
|
modbus_tcp_t *ctx_tcp;
|
||||||
|
size_t dest_size;
|
||||||
|
size_t ret_size;
|
||||||
|
|
||||||
|
#if defined(OS_BSD)
|
||||||
|
/* MSG_NOSIGNAL is unsupported on *BSD so we install an ignore
|
||||||
|
handler for SIGPIPE. */
|
||||||
|
struct sigaction sa;
|
||||||
|
|
||||||
|
sa.sa_handler = SIG_IGN;
|
||||||
|
if (sigaction(SIGPIPE, &sa, NULL) < 0) {
|
||||||
|
/* The debug flag can't be set here... */
|
||||||
|
fprintf(stderr, "Could not install SIGPIPE handler.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctx = (modbus_t *)malloc(sizeof(modbus_t));
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
_modbus_init_common(ctx);
|
||||||
|
|
||||||
|
/* Could be changed after to reach a remote serial Modbus device */
|
||||||
|
ctx->slave = MODBUS_TCP_SLAVE;
|
||||||
|
|
||||||
|
ctx->backend = &_modbus_tcp_backend;
|
||||||
|
|
||||||
|
ctx->backend_data = (modbus_tcp_t *)malloc(sizeof(modbus_tcp_t));
|
||||||
|
if (ctx->backend_data == NULL) {
|
||||||
|
modbus_free(ctx);
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ctx_tcp = (modbus_tcp_t *)ctx->backend_data;
|
||||||
|
|
||||||
|
if (ip != NULL) {
|
||||||
|
dest_size = sizeof(char) * 16;
|
||||||
|
ret_size = strlcpy(ctx_tcp->ip, ip, dest_size);
|
||||||
|
if (ret_size == 0) {
|
||||||
|
fprintf(stderr, "The IP string is empty\n");
|
||||||
|
modbus_free(ctx);
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret_size >= dest_size) {
|
||||||
|
fprintf(stderr, "The IP string has been truncated\n");
|
||||||
|
modbus_free(ctx);
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx_tcp->ip[0] = '0';
|
||||||
|
}
|
||||||
|
ctx_tcp->port = port;
|
||||||
|
ctx_tcp->t_id = 0;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
modbus_t* modbus_new_tcp_pi(const char *node, const char *service)
|
||||||
|
{
|
||||||
|
modbus_t *ctx;
|
||||||
|
modbus_tcp_pi_t *ctx_tcp_pi;
|
||||||
|
size_t dest_size;
|
||||||
|
size_t ret_size;
|
||||||
|
|
||||||
|
ctx = (modbus_t *)malloc(sizeof(modbus_t));
|
||||||
|
if (ctx == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
_modbus_init_common(ctx);
|
||||||
|
|
||||||
|
/* Could be changed after to reach a remote serial Modbus device */
|
||||||
|
ctx->slave = MODBUS_TCP_SLAVE;
|
||||||
|
|
||||||
|
ctx->backend = &_modbus_tcp_pi_backend;
|
||||||
|
|
||||||
|
ctx->backend_data = (modbus_tcp_pi_t *)malloc(sizeof(modbus_tcp_pi_t));
|
||||||
|
if (ctx->backend_data == NULL) {
|
||||||
|
modbus_free(ctx);
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ctx_tcp_pi = (modbus_tcp_pi_t *)ctx->backend_data;
|
||||||
|
|
||||||
|
if (node == NULL) {
|
||||||
|
/* The node argument can be empty to indicate any hosts */
|
||||||
|
ctx_tcp_pi->node[0] = 0;
|
||||||
|
} else {
|
||||||
|
dest_size = sizeof(char) * _MODBUS_TCP_PI_NODE_LENGTH;
|
||||||
|
ret_size = strlcpy(ctx_tcp_pi->node, node, dest_size);
|
||||||
|
if (ret_size == 0) {
|
||||||
|
fprintf(stderr, "The node string is empty\n");
|
||||||
|
modbus_free(ctx);
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret_size >= dest_size) {
|
||||||
|
fprintf(stderr, "The node string has been truncated\n");
|
||||||
|
modbus_free(ctx);
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (service != NULL) {
|
||||||
|
dest_size = sizeof(char) * _MODBUS_TCP_PI_SERVICE_LENGTH;
|
||||||
|
ret_size = strlcpy(ctx_tcp_pi->service, service, dest_size);
|
||||||
|
} else {
|
||||||
|
/* Empty service is not allowed, error catched below. */
|
||||||
|
ret_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret_size == 0) {
|
||||||
|
fprintf(stderr, "The service string is empty\n");
|
||||||
|
modbus_free(ctx);
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret_size >= dest_size) {
|
||||||
|
fprintf(stderr, "The service string has been truncated\n");
|
||||||
|
modbus_free(ctx);
|
||||||
|
errno = EINVAL;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx_tcp_pi->t_id = 0;
|
||||||
|
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
52
src/modbus-tcp.h
Normal file
52
src/modbus-tcp.h
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2001-2010 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODBUS_TCP_H
|
||||||
|
#define MODBUS_TCP_H
|
||||||
|
|
||||||
|
#include "modbus.h"
|
||||||
|
|
||||||
|
MODBUS_BEGIN_DECLS
|
||||||
|
|
||||||
|
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||||
|
/* Win32 with MinGW, supplement to <errno.h> */
|
||||||
|
#include <winsock2.h>
|
||||||
|
#if !defined(ECONNRESET)
|
||||||
|
#define ECONNRESET WSAECONNRESET
|
||||||
|
#endif
|
||||||
|
#if !defined(ECONNREFUSED)
|
||||||
|
#define ECONNREFUSED WSAECONNREFUSED
|
||||||
|
#endif
|
||||||
|
#if !defined(ETIMEDOUT)
|
||||||
|
#define ETIMEDOUT WSAETIMEDOUT
|
||||||
|
#endif
|
||||||
|
#if !defined(ENOPROTOOPT)
|
||||||
|
#define ENOPROTOOPT WSAENOPROTOOPT
|
||||||
|
#endif
|
||||||
|
#if !defined(EINPROGRESS)
|
||||||
|
#define EINPROGRESS WSAEINPROGRESS
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MODBUS_TCP_DEFAULT_PORT 502
|
||||||
|
#define MODBUS_TCP_SLAVE 0xFF
|
||||||
|
|
||||||
|
/* Modbus_Application_Protocol_V1_1b.pdf Chapter 4 Section 1 Page 5
|
||||||
|
* TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes
|
||||||
|
*/
|
||||||
|
#define MODBUS_TCP_MAX_ADU_LENGTH 260
|
||||||
|
|
||||||
|
MODBUS_API modbus_t* modbus_new_tcp(const char *ip_address, int port);
|
||||||
|
MODBUS_API int modbus_tcp_listen(modbus_t *ctx, int nb_connection);
|
||||||
|
MODBUS_API int modbus_tcp_accept(modbus_t *ctx, int *s);
|
||||||
|
|
||||||
|
MODBUS_API modbus_t* modbus_new_tcp_pi(const char *node, const char *service);
|
||||||
|
MODBUS_API int modbus_tcp_pi_listen(modbus_t *ctx, int nb_connection);
|
||||||
|
MODBUS_API int modbus_tcp_pi_accept(modbus_t *ctx, int *s);
|
||||||
|
|
||||||
|
MODBUS_END_DECLS
|
||||||
|
|
||||||
|
#endif /* MODBUS_TCP_H */
|
||||||
53
src/modbus-version.h
Normal file
53
src/modbus-version.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2010-2014 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODBUS_VERSION_H
|
||||||
|
#define MODBUS_VERSION_H
|
||||||
|
|
||||||
|
/* The major version, (1, if %LIBMODBUS_VERSION is 1.2.3) */
|
||||||
|
#define LIBMODBUS_VERSION_MAJOR (3)
|
||||||
|
|
||||||
|
/* The minor version (2, if %LIBMODBUS_VERSION is 1.2.3) */
|
||||||
|
#define LIBMODBUS_VERSION_MINOR (1)
|
||||||
|
|
||||||
|
/* The micro version (3, if %LIBMODBUS_VERSION is 1.2.3) */
|
||||||
|
#define LIBMODBUS_VERSION_MICRO (6)
|
||||||
|
|
||||||
|
/* The full version, like 1.2.3 */
|
||||||
|
#define LIBMODBUS_VERSION 3.1.6
|
||||||
|
|
||||||
|
/* The full version, in string form (suited for string concatenation)
|
||||||
|
*/
|
||||||
|
#define LIBMODBUS_VERSION_STRING "3.1.6"
|
||||||
|
|
||||||
|
/* Numerically encoded version, eg. v1.2.3 is 0x010203 */
|
||||||
|
#define LIBMODBUS_VERSION_HEX ((LIBMODBUS_VERSION_MAJOR << 16) | \
|
||||||
|
(LIBMODBUS_VERSION_MINOR << 8) | \
|
||||||
|
(LIBMODBUS_VERSION_MICRO << 0))
|
||||||
|
|
||||||
|
/* Evaluates to True if the version is greater than @major, @minor and @micro
|
||||||
|
*/
|
||||||
|
#define LIBMODBUS_VERSION_CHECK(major,minor,micro) \
|
||||||
|
(LIBMODBUS_VERSION_MAJOR > (major) || \
|
||||||
|
(LIBMODBUS_VERSION_MAJOR == (major) && \
|
||||||
|
LIBMODBUS_VERSION_MINOR > (minor)) || \
|
||||||
|
(LIBMODBUS_VERSION_MAJOR == (major) && \
|
||||||
|
LIBMODBUS_VERSION_MINOR == (minor) && \
|
||||||
|
LIBMODBUS_VERSION_MICRO >= (micro)))
|
||||||
|
|
||||||
|
#endif /* MODBUS_VERSION_H */
|
||||||
1911
src/modbus.c
Normal file
1911
src/modbus.c
Normal file
File diff suppressed because it is too large
Load Diff
293
src/modbus.h
Normal file
293
src/modbus.h
Normal file
@ -0,0 +1,293 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2001-2013 Stéphane Raimbault <stephane.raimbault@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1+
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODBUS_H
|
||||||
|
#define MODBUS_H
|
||||||
|
|
||||||
|
/* Add this for macros that defined unix flavor */
|
||||||
|
#if (defined(__unix__) || defined(unix)) && !defined(USG)
|
||||||
|
#include <sys/param.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#include <stdint.h>
|
||||||
|
#else
|
||||||
|
#include "stdint.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "modbus-version.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
# if defined(DLLBUILD)
|
||||||
|
/* define DLLBUILD when building the DLL */
|
||||||
|
# define MODBUS_API __declspec(dllexport)
|
||||||
|
# else
|
||||||
|
# define MODBUS_API __declspec(dllimport)
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# define MODBUS_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# define MODBUS_BEGIN_DECLS extern "C" {
|
||||||
|
# define MODBUS_END_DECLS }
|
||||||
|
#else
|
||||||
|
# define MODBUS_BEGIN_DECLS
|
||||||
|
# define MODBUS_END_DECLS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MODBUS_BEGIN_DECLS
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef OFF
|
||||||
|
#define OFF 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ON
|
||||||
|
#define ON 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Modbus function codes */
|
||||||
|
#define MODBUS_FC_READ_COILS 0x01
|
||||||
|
#define MODBUS_FC_READ_DISCRETE_INPUTS 0x02
|
||||||
|
#define MODBUS_FC_READ_HOLDING_REGISTERS 0x03
|
||||||
|
#define MODBUS_FC_READ_INPUT_REGISTERS 0x04
|
||||||
|
#define MODBUS_FC_WRITE_SINGLE_COIL 0x05
|
||||||
|
#define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06
|
||||||
|
#define MODBUS_FC_READ_EXCEPTION_STATUS 0x07
|
||||||
|
#define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F
|
||||||
|
#define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10
|
||||||
|
#define MODBUS_FC_REPORT_SLAVE_ID 0x11
|
||||||
|
#define MODBUS_FC_MASK_WRITE_REGISTER 0x16
|
||||||
|
#define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17
|
||||||
|
|
||||||
|
#define MODBUS_BROADCAST_ADDRESS 0
|
||||||
|
|
||||||
|
/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)
|
||||||
|
* Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0)
|
||||||
|
* (chapter 6 section 11 page 29)
|
||||||
|
* Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0)
|
||||||
|
*/
|
||||||
|
#define MODBUS_MAX_READ_BITS 2000
|
||||||
|
#define MODBUS_MAX_WRITE_BITS 1968
|
||||||
|
|
||||||
|
/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15)
|
||||||
|
* Quantity of Registers to read (2 bytes): 1 to 125 (0x7D)
|
||||||
|
* (chapter 6 section 12 page 31)
|
||||||
|
* Quantity of Registers to write (2 bytes) 1 to 123 (0x7B)
|
||||||
|
* (chapter 6 section 17 page 38)
|
||||||
|
* Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79)
|
||||||
|
*/
|
||||||
|
#define MODBUS_MAX_READ_REGISTERS 125
|
||||||
|
#define MODBUS_MAX_WRITE_REGISTERS 123
|
||||||
|
#define MODBUS_MAX_WR_WRITE_REGISTERS 121
|
||||||
|
#define MODBUS_MAX_WR_READ_REGISTERS 125
|
||||||
|
|
||||||
|
/* The size of the MODBUS PDU is limited by the size constraint inherited from
|
||||||
|
* the first MODBUS implementation on Serial Line network (max. RS485 ADU = 256
|
||||||
|
* bytes). Therefore, MODBUS PDU for serial line communication = 256 - Server
|
||||||
|
* address (1 byte) - CRC (2 bytes) = 253 bytes.
|
||||||
|
*/
|
||||||
|
#define MODBUS_MAX_PDU_LENGTH 253
|
||||||
|
|
||||||
|
/* Consequently:
|
||||||
|
* - RTU MODBUS ADU = 253 bytes + Server address (1 byte) + CRC (2 bytes) = 256
|
||||||
|
* bytes.
|
||||||
|
* - TCP MODBUS ADU = 253 bytes + MBAP (7 bytes) = 260 bytes.
|
||||||
|
* so the maximum of both backend in 260 bytes. This size can used to allocate
|
||||||
|
* an array of bytes to store responses and it will be compatible with the two
|
||||||
|
* backends.
|
||||||
|
*/
|
||||||
|
#define MODBUS_MAX_ADU_LENGTH 260
|
||||||
|
|
||||||
|
/* Random number to avoid errno conflicts */
|
||||||
|
#define MODBUS_ENOBASE 112345678
|
||||||
|
|
||||||
|
/* Protocol exceptions */
|
||||||
|
enum {
|
||||||
|
MODBUS_EXCEPTION_ILLEGAL_FUNCTION = 0x01,
|
||||||
|
MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,
|
||||||
|
MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,
|
||||||
|
MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,
|
||||||
|
MODBUS_EXCEPTION_ACKNOWLEDGE,
|
||||||
|
MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,
|
||||||
|
MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,
|
||||||
|
MODBUS_EXCEPTION_MEMORY_PARITY,
|
||||||
|
MODBUS_EXCEPTION_NOT_DEFINED,
|
||||||
|
MODBUS_EXCEPTION_GATEWAY_PATH,
|
||||||
|
MODBUS_EXCEPTION_GATEWAY_TARGET,
|
||||||
|
MODBUS_EXCEPTION_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EMBXILFUN (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_FUNCTION)
|
||||||
|
#define EMBXILADD (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS)
|
||||||
|
#define EMBXILVAL (MODBUS_ENOBASE + MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE)
|
||||||
|
#define EMBXSFAIL (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE)
|
||||||
|
#define EMBXACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_ACKNOWLEDGE)
|
||||||
|
#define EMBXSBUSY (MODBUS_ENOBASE + MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY)
|
||||||
|
#define EMBXNACK (MODBUS_ENOBASE + MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE)
|
||||||
|
#define EMBXMEMPAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_MEMORY_PARITY)
|
||||||
|
#define EMBXGPATH (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_PATH)
|
||||||
|
#define EMBXGTAR (MODBUS_ENOBASE + MODBUS_EXCEPTION_GATEWAY_TARGET)
|
||||||
|
|
||||||
|
/* Native libmodbus error codes */
|
||||||
|
#define EMBBADCRC (EMBXGTAR + 1)
|
||||||
|
#define EMBBADDATA (EMBXGTAR + 2)
|
||||||
|
#define EMBBADEXC (EMBXGTAR + 3)
|
||||||
|
#define EMBUNKEXC (EMBXGTAR + 4)
|
||||||
|
#define EMBMDATA (EMBXGTAR + 5)
|
||||||
|
#define EMBBADSLAVE (EMBXGTAR + 6)
|
||||||
|
|
||||||
|
extern const unsigned int libmodbus_version_major;
|
||||||
|
extern const unsigned int libmodbus_version_minor;
|
||||||
|
extern const unsigned int libmodbus_version_micro;
|
||||||
|
|
||||||
|
typedef struct _modbus modbus_t;
|
||||||
|
|
||||||
|
typedef struct _modbus_mapping_t {
|
||||||
|
int nb_bits;
|
||||||
|
int start_bits;
|
||||||
|
int nb_input_bits;
|
||||||
|
int start_input_bits;
|
||||||
|
int nb_input_registers;
|
||||||
|
int start_input_registers;
|
||||||
|
int nb_registers;
|
||||||
|
int start_registers;
|
||||||
|
uint8_t *tab_bits;
|
||||||
|
uint8_t *tab_input_bits;
|
||||||
|
uint16_t *tab_input_registers;
|
||||||
|
uint16_t *tab_registers;
|
||||||
|
} modbus_mapping_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MODBUS_ERROR_RECOVERY_NONE = 0,
|
||||||
|
MODBUS_ERROR_RECOVERY_LINK = (1<<1),
|
||||||
|
MODBUS_ERROR_RECOVERY_PROTOCOL = (1<<2)
|
||||||
|
} modbus_error_recovery_mode;
|
||||||
|
|
||||||
|
MODBUS_API int modbus_set_slave(modbus_t* ctx, int slave);
|
||||||
|
MODBUS_API int modbus_get_slave(modbus_t* ctx);
|
||||||
|
MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery);
|
||||||
|
MODBUS_API int modbus_set_socket(modbus_t *ctx, int s);
|
||||||
|
MODBUS_API int modbus_get_socket(modbus_t *ctx);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
|
||||||
|
MODBUS_API int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
|
||||||
|
MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec);
|
||||||
|
MODBUS_API int modbus_set_indication_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_get_header_length(modbus_t *ctx);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_connect(modbus_t *ctx);
|
||||||
|
MODBUS_API void modbus_close(modbus_t *ctx);
|
||||||
|
|
||||||
|
MODBUS_API void modbus_free(modbus_t *ctx);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_flush(modbus_t *ctx);
|
||||||
|
MODBUS_API int modbus_set_debug(modbus_t *ctx, int flag);
|
||||||
|
|
||||||
|
MODBUS_API const char *modbus_strerror(int errnum);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
|
||||||
|
MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest);
|
||||||
|
MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
|
||||||
|
MODBUS_API int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest);
|
||||||
|
MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status);
|
||||||
|
MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, const uint16_t value);
|
||||||
|
MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data);
|
||||||
|
MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data);
|
||||||
|
MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask);
|
||||||
|
MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,
|
||||||
|
const uint16_t *src, int read_addr, int read_nb,
|
||||||
|
uint16_t *dest);
|
||||||
|
MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);
|
||||||
|
|
||||||
|
MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address(
|
||||||
|
unsigned int start_bits, unsigned int nb_bits,
|
||||||
|
unsigned int start_input_bits, unsigned int nb_input_bits,
|
||||||
|
unsigned int start_registers, unsigned int nb_registers,
|
||||||
|
unsigned int start_input_registers, unsigned int nb_input_registers);
|
||||||
|
|
||||||
|
MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,
|
||||||
|
int nb_registers, int nb_input_registers);
|
||||||
|
MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);
|
||||||
|
|
||||||
|
MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req,
|
||||||
|
int req_length, modbus_mapping_t *mb_mapping);
|
||||||
|
MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,
|
||||||
|
unsigned int exception_code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTILS FUNCTIONS
|
||||||
|
**/
|
||||||
|
|
||||||
|
#define MODBUS_GET_HIGH_BYTE(data) (((data) >> 8) & 0xFF)
|
||||||
|
#define MODBUS_GET_LOW_BYTE(data) ((data) & 0xFF)
|
||||||
|
#define MODBUS_GET_INT64_FROM_INT16(tab_int16, index) \
|
||||||
|
(((int64_t)tab_int16[(index) ] << 48) + \
|
||||||
|
((int64_t)tab_int16[(index) + 1] << 32) + \
|
||||||
|
((int64_t)tab_int16[(index) + 2] << 16) + \
|
||||||
|
(int64_t)tab_int16[(index) + 3])
|
||||||
|
#define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) ((tab_int16[(index)] << 16) + tab_int16[(index) + 1])
|
||||||
|
#define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) ((tab_int8[(index)] << 8) + tab_int8[(index) + 1])
|
||||||
|
#define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) \
|
||||||
|
do { \
|
||||||
|
tab_int8[(index)] = (value) >> 8; \
|
||||||
|
tab_int8[(index) + 1] = (value) & 0xFF; \
|
||||||
|
} while (0)
|
||||||
|
#define MODBUS_SET_INT32_TO_INT16(tab_int16, index, value) \
|
||||||
|
do { \
|
||||||
|
tab_int16[(index) ] = (value) >> 16; \
|
||||||
|
tab_int16[(index) + 1] = (value); \
|
||||||
|
} while (0)
|
||||||
|
#define MODBUS_SET_INT64_TO_INT16(tab_int16, index, value) \
|
||||||
|
do { \
|
||||||
|
tab_int16[(index) ] = (value) >> 48; \
|
||||||
|
tab_int16[(index) + 1] = (value) >> 32; \
|
||||||
|
tab_int16[(index) + 2] = (value) >> 16; \
|
||||||
|
tab_int16[(index) + 3] = (value); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
MODBUS_API void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value);
|
||||||
|
MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,
|
||||||
|
const uint8_t *tab_byte);
|
||||||
|
MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits);
|
||||||
|
MODBUS_API float modbus_get_float(const uint16_t *src);
|
||||||
|
MODBUS_API float modbus_get_float_abcd(const uint16_t *src);
|
||||||
|
MODBUS_API float modbus_get_float_dcba(const uint16_t *src);
|
||||||
|
MODBUS_API float modbus_get_float_badc(const uint16_t *src);
|
||||||
|
MODBUS_API float modbus_get_float_cdab(const uint16_t *src);
|
||||||
|
|
||||||
|
MODBUS_API void modbus_set_float(float f, uint16_t *dest);
|
||||||
|
MODBUS_API void modbus_set_float_abcd(float f, uint16_t *dest);
|
||||||
|
MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest);
|
||||||
|
MODBUS_API void modbus_set_float_badc(float f, uint16_t *dest);
|
||||||
|
MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);
|
||||||
|
|
||||||
|
#include "modbus-tcp.h"
|
||||||
|
#include "modbus-rtu.h"
|
||||||
|
|
||||||
|
MODBUS_END_DECLS
|
||||||
|
|
||||||
|
#endif /* MODBUS_H */
|
||||||
BIN
src/modbus.lib
Normal file
BIN
src/modbus.lib
Normal file
Binary file not shown.
457
thread.cpp
Normal file
457
thread.cpp
Normal file
@ -0,0 +1,457 @@
|
|||||||
|
|
||||||
|
#include "thread.h"
|
||||||
|
#include <QModbusRtuSerialMaster>
|
||||||
|
#include <QModbusDataUnit>
|
||||||
|
#include <QModbusReply>
|
||||||
|
#include <QVariant>
|
||||||
|
#include <QSerialPort>
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
extern camera *m_camera;
|
||||||
|
extern correct *m_correct;
|
||||||
|
|
||||||
|
extern uint8_t learning_flag;
|
||||||
|
extern Process_img * process_img;
|
||||||
|
cv::Mat mat_1;
|
||||||
|
cv::Mat mat_2;
|
||||||
|
cv::Mat img_pop;
|
||||||
|
extern int save_flag;
|
||||||
|
int m_index1;
|
||||||
|
QSemaphore usebuff(0);
|
||||||
|
QSemaphore read_to_send(0);
|
||||||
|
//unsigned char *send_buf;
|
||||||
|
char *recv_buf;
|
||||||
|
|
||||||
|
extern uint8_t adjust_correct_flag;
|
||||||
|
|
||||||
|
#define WHITE_IMAGE_PATH "C:/Users/USER/Desktop/wood_aduiduiduiplus/build-wooden-Desktop_Qt_5_9_5_MSVC2017_64bit-Release/white"
|
||||||
|
#define BLACK_IMAGE_PATH "C:/Users/USER/Desktop/wood_aduiduiduiplus/build-wooden-Desktop_Qt_5_9_5_MSVC2017_64bit-Release/black"
|
||||||
|
#define correct_path "D:/correct.png"
|
||||||
|
int get_height(cv::Mat img)
|
||||||
|
{
|
||||||
|
int b_temp = 0;
|
||||||
|
float b_avg = 0.0;
|
||||||
|
int i, j;
|
||||||
|
for(i = 0; i < img.rows; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < img.cols; j++)
|
||||||
|
{
|
||||||
|
b_temp += (int)img.at<cv::Vec3b>(i, j)[0];
|
||||||
|
}
|
||||||
|
b_avg = b_temp / 4096.0f;
|
||||||
|
if(b_avg == 0)
|
||||||
|
{
|
||||||
|
// qDebug() << i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
b_temp = 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
//采集
|
||||||
|
void onImageDataCallback(SapXferCallbackInfo *pInfo)
|
||||||
|
{
|
||||||
|
qDebug() << "enter to calback" ;
|
||||||
|
if(pInfo)
|
||||||
|
{
|
||||||
|
|
||||||
|
unsigned char *pData;
|
||||||
|
int width = m_camera->m_buffer->GetWidth();
|
||||||
|
int height = m_camera->m_buffer->GetHeight();
|
||||||
|
qDebug() << "enter to calback: limian";
|
||||||
|
|
||||||
|
m_camera->m_buffer->GetAddress((void**)&pData);
|
||||||
|
cv::Mat img(height, width, CV_8UC3, pData);
|
||||||
|
img.convertTo(img, CV_32FC3);
|
||||||
|
m_camera->calibrated_img = (img - m_camera->black_mat) / (m_camera->white_mat - m_camera->black_mat + m_camera->eps);
|
||||||
|
m_camera->calibrated_img *= 255;
|
||||||
|
m_camera->calibrated_img.convertTo(m_camera->calibrated_img, CV_8UC3);
|
||||||
|
|
||||||
|
m_camera->rgb_height = get_height(img);
|
||||||
|
// qDebug() << "rgb_height: " << rgb_height;
|
||||||
|
|
||||||
|
if(m_camera->rgb_height < 3000 && m_camera->rgb_height > 500 && !adjust_correct_flag)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_camera->imgqueue.push(m_camera->calibrated_img);
|
||||||
|
|
||||||
|
// m_camera->imgqueue.push(mat_2);
|
||||||
|
// emit process_img->show_img(mat_1);
|
||||||
|
// usebuff.release();
|
||||||
|
// if(!learning_flag)
|
||||||
|
// read_to_send.release();
|
||||||
|
}
|
||||||
|
else if(adjust_correct_flag)
|
||||||
|
{
|
||||||
|
img.convertTo(img, CV_8UC3);
|
||||||
|
mat_1 = img;
|
||||||
|
usebuff.release();
|
||||||
|
}
|
||||||
|
else if(m_camera->rgb_height == 0 || m_camera->rgb_height == -1)
|
||||||
|
{
|
||||||
|
|
||||||
|
m_camera->m_buffer->Clear();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//校正
|
||||||
|
void onImageCorrectCallback(SapXferCallbackInfo *pInfo)
|
||||||
|
{
|
||||||
|
qDebug() <<"11111111222222222333333333";
|
||||||
|
qDebug() << " onImageCorrectCallback start ";
|
||||||
|
//采集黑白帧
|
||||||
|
if(pInfo)
|
||||||
|
{
|
||||||
|
qDebug() << "pInfo";
|
||||||
|
if( m_camera->capture_black_flag || m_camera->capture_white_flag )
|
||||||
|
{
|
||||||
|
qDebug() << "flag";
|
||||||
|
|
||||||
|
unsigned char pdata_rgb;
|
||||||
|
void* pDataAddr_rgb = &pdata_rgb;
|
||||||
|
m_camera->m_buffer->GetAddress(&pDataAddr_rgb);
|
||||||
|
cv::Mat img(4096, 3000, CV_8UC3,pDataAddr_rgb);
|
||||||
|
img.convertTo(img, CV_32FC3);
|
||||||
|
if( m_camera->capture_black_flag )
|
||||||
|
{
|
||||||
|
qDebug() << "capture_black_flag";
|
||||||
|
m_camera->capture_black_flag = false;
|
||||||
|
m_camera->black_mat = img;
|
||||||
|
qDebug() << "img";
|
||||||
|
FILE* fp = fopen(BLACK_IMAGE_PATH, "wb");
|
||||||
|
fwrite(m_camera->black_mat.data, 4096*3000*3*4, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
qDebug() << "black frame acquisition OK!";
|
||||||
|
}
|
||||||
|
else if( m_camera->capture_white_flag )
|
||||||
|
{
|
||||||
|
m_camera->capture_white_flag = false;
|
||||||
|
m_camera->white_mat = img;
|
||||||
|
FILE* fp = fopen(WHITE_IMAGE_PATH, "wb");
|
||||||
|
fwrite(m_camera->white_mat.data, 4096*3000*3*4, 1, fp);
|
||||||
|
fclose(fp);
|
||||||
|
qDebug() << " white frame acquisition OK!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Widget::getInstance()->set();
|
||||||
|
}
|
||||||
|
|
||||||
|
Process_img::Process_img(QObject *parent) : QThread(parent), m_stop(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process_img::run()
|
||||||
|
{
|
||||||
|
qDebug() << "process_imgID: " << currentThreadId();
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
stop_mutex.lock();
|
||||||
|
if(m_stop)
|
||||||
|
{
|
||||||
|
stop_mutex.unlock();
|
||||||
|
qDebug() << "process thread quit______________________";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stop_mutex.unlock();
|
||||||
|
|
||||||
|
if(m_camera->imgqueue.size()>1)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// read_to_send.acquire(); //没有mat_2就阻塞
|
||||||
|
|
||||||
|
m_camera->imgqueue.pop();
|
||||||
|
qDebug()<<"the wood image's queue size: "<<m_camera->imgqueue.size();
|
||||||
|
img_pop = m_camera->imgqueue.front();
|
||||||
|
img_pop = m_camera->calibrated_img(cv::Rect(0, 0, 4096, m_camera->rgb_height)); //4096
|
||||||
|
|
||||||
|
int save_count = 0;
|
||||||
|
save_count++;
|
||||||
|
|
||||||
|
if(save_flag && save_count == 1)
|
||||||
|
{
|
||||||
|
qDebug() << "1111111111111";
|
||||||
|
// QDateTime time = QDateTime::currentDateTime();
|
||||||
|
// QString str = time.toString("yyyyMMddhhmmss");
|
||||||
|
// QString filepath = SAVE_IMAGE_PATH + str + ".png";
|
||||||
|
// qDebug() << filepath;
|
||||||
|
// cv::imwrite(filepath.toLatin1().data(), img);
|
||||||
|
|
||||||
|
char fileName[64];
|
||||||
|
sprintf(fileName, "D:/save_image/rgb%d.bmp", m_index1);
|
||||||
|
|
||||||
|
m_index1++;
|
||||||
|
qDebug() << fileName;
|
||||||
|
cv::imwrite(fileName, img_pop);
|
||||||
|
save_count = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
emit process_img->show_img(img_pop);
|
||||||
|
usebuff.release();
|
||||||
|
if(!learning_flag)
|
||||||
|
read_to_send.release();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(!usebuff.tryAcquire())
|
||||||
|
// continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Process_img::exitThread()
|
||||||
|
{
|
||||||
|
stop_mutex.lock();
|
||||||
|
m_stop = true;
|
||||||
|
stop_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Adjust_para::Adjust_para(QObject *parent) : QThread(parent), is_stop(false), correct_flag(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adjust_para::run()
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
stop_mutex.lock();
|
||||||
|
if(is_stop)
|
||||||
|
{
|
||||||
|
stop_mutex.unlock();
|
||||||
|
qDebug() << "adjust thread qiut_______________________";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stop_mutex.unlock();
|
||||||
|
if(!usebuff.tryAcquire())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
qDebug() << "234";
|
||||||
|
|
||||||
|
emit(send_image_debug(mat_1));
|
||||||
|
|
||||||
|
correct_mutex.lock();
|
||||||
|
|
||||||
|
qDebug() << "aabbbbbbbcccccc";
|
||||||
|
|
||||||
|
if(correct_flag)
|
||||||
|
{
|
||||||
|
cv::imwrite(correct_path, mat_1);
|
||||||
|
correct_flag = false;
|
||||||
|
}
|
||||||
|
correct_mutex.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adjust_para::get_correct_signal()
|
||||||
|
{
|
||||||
|
correct_mutex.lock();
|
||||||
|
correct_flag = true;
|
||||||
|
// qDebug() << "llllllllllll";
|
||||||
|
correct_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Adjust_para::exitThread()
|
||||||
|
{
|
||||||
|
stop_mutex.lock();
|
||||||
|
is_stop = true;
|
||||||
|
stop_mutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SendThread::SendThread(QObject *parent) : QThread(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SendThread::run()
|
||||||
|
{
|
||||||
|
bool is_timeout;
|
||||||
|
cv::Mat temp_img;
|
||||||
|
unsigned char* send_buf;
|
||||||
|
|
||||||
|
send_server = new QTcpServer();
|
||||||
|
send_server->listen(QHostAddress::Any, 21122);
|
||||||
|
qDebug() << "sendthread waiting connect.....";
|
||||||
|
send_server->waitForNewConnection(50000, &is_timeout);
|
||||||
|
if(is_timeout)
|
||||||
|
{
|
||||||
|
qDebug() << "sendthread time out";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
send_socket = send_server->nextPendingConnection();
|
||||||
|
qDebug() << "sendsocket new connection";
|
||||||
|
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
if(!usebuff.tryAcquire())
|
||||||
|
continue;
|
||||||
|
read_to_send.acquire();
|
||||||
|
temp_img = img_pop;
|
||||||
|
// emit process_img->show_img(img_pop);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
send_buf = (uint8_t*)malloc(temp_img.cols * temp_img.rows * 3 + 16);
|
||||||
|
memset(send_buf, 0, temp_img.cols * temp_img.rows * 3 + 16);
|
||||||
|
|
||||||
|
uint16_t width = temp_img.cols;
|
||||||
|
uint16_t height = temp_img.rows;
|
||||||
|
uint32_t data_len = width * height * 3 + 8;
|
||||||
|
|
||||||
|
//协议
|
||||||
|
send_buf[0] = 0xAA;
|
||||||
|
// 总体报文长度
|
||||||
|
for(int i = 1; i<= 4; i++)
|
||||||
|
send_buf[i] = (uint8_t)(data_len >> 8 * (4 - i));
|
||||||
|
// 数据和指令部分
|
||||||
|
send_buf[5] = ' ';
|
||||||
|
send_buf[6] = ' ';
|
||||||
|
send_buf[7] = 'I';
|
||||||
|
send_buf[8] = 'M';
|
||||||
|
send_buf[9] = (uint8_t)(height>>8) & 0xFF;
|
||||||
|
send_buf[10] = (uint8_t)height;
|
||||||
|
send_buf[11] = (uint8_t)(width>>8) & 0xFF;
|
||||||
|
send_buf[12] = (uint8_t)width;
|
||||||
|
memcpy(send_buf + 13, temp_img.data, temp_img.cols*temp_img.rows*3+4);
|
||||||
|
// 末尾校验位、协议位
|
||||||
|
send_buf[temp_img.cols * temp_img.rows*3 + 13] = 0xFF;
|
||||||
|
send_buf[temp_img.cols * temp_img.rows*3 + 14] = 0xFF;
|
||||||
|
send_buf[temp_img.cols * temp_img.rows*3 + 15] = 0xBB;
|
||||||
|
|
||||||
|
send_socket->write((const char*)send_buf, (temp_img.cols * temp_img.rows * 3 + 16)*sizeof(unsigned char));
|
||||||
|
send_socket->flush();
|
||||||
|
|
||||||
|
qDebug() << "====send success====";
|
||||||
|
|
||||||
|
|
||||||
|
free(send_buf);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RecvThread::RecvThread(QObject *parent) : QThread(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RecvThread::run()
|
||||||
|
{
|
||||||
|
bool is_timeout;
|
||||||
|
char buf[1100] = {0};
|
||||||
|
int len = 0;
|
||||||
|
recv_server = new QTcpServer();
|
||||||
|
recv_server->listen(QHostAddress::Any, 21123);
|
||||||
|
qDebug() << "recvthread waiting connect.....";
|
||||||
|
|
||||||
|
recv_server->waitForNewConnection(50000, &is_timeout);
|
||||||
|
if(is_timeout == true)
|
||||||
|
{
|
||||||
|
qDebug() << "recvthread time out";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
recv_socket = recv_server->nextPendingConnection();
|
||||||
|
qDebug() << "recvthread new connection";
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
/***
|
||||||
|
// memset(buf, 0, 10);
|
||||||
|
// recv_socket->waitForReadyRead(-1); //没有东西就阻塞
|
||||||
|
// len = recv_socket->read(buf, 10);
|
||||||
|
|
||||||
|
//// emit read_plc();
|
||||||
|
|
||||||
|
// if(len < 0)
|
||||||
|
// {
|
||||||
|
// qDebug() << "receive data error";
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// qDebug() << "receive :" << len;
|
||||||
|
// FILE* fp;
|
||||||
|
// fp = fopen("C:/Users/USER/Desktop/1.txt", "a+");
|
||||||
|
// fwrite(buf, 1, 1, fp);
|
||||||
|
// fclose(fp);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// emit send_sortingResult(buf);
|
||||||
|
***/
|
||||||
|
memset(buf, 0, 1100);//初始化为0
|
||||||
|
recv_socket->waitForReadyRead(-1);//阻塞
|
||||||
|
qDebug() << "======receive success======";
|
||||||
|
len = recv_socket->read(buf, 1100);
|
||||||
|
qDebug() << "len" << len;
|
||||||
|
char buf1[1100] = {0};
|
||||||
|
for(int i = 0; i < 1080; i++)
|
||||||
|
{
|
||||||
|
// qDebug() << "buf" << buf[i] << i;
|
||||||
|
buf1[i] = buf[i+6];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(len < 0)
|
||||||
|
{
|
||||||
|
// qDebug() << "receiv data error";
|
||||||
|
}
|
||||||
|
else if(len < 10)
|
||||||
|
{
|
||||||
|
// qDebug() << "receive:" << len;
|
||||||
|
emit send_sortingResult(buf);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug() << "KM";
|
||||||
|
//需要把获得的buf数据发送到showpic里
|
||||||
|
emit SendPicInfo(buf1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RestartThread::RestartThread(QObject *parent) : QThread(parent), restr_flag(false)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestartThread::run()
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
restr_mutex.lock();
|
||||||
|
if(restr_flag)
|
||||||
|
{
|
||||||
|
// restr_mutex.unlock();
|
||||||
|
m_camera->openCamera();
|
||||||
|
qDebug() << "aa";
|
||||||
|
restr_flag = false;
|
||||||
|
qDebug() << "bb";
|
||||||
|
}
|
||||||
|
msleep(1);
|
||||||
|
restr_mutex.unlock();
|
||||||
|
msleep(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestartThread::restr_fun()
|
||||||
|
{
|
||||||
|
restr_mutex.lock();
|
||||||
|
restr_flag = true;
|
||||||
|
restr_mutex.unlock();
|
||||||
|
}
|
||||||
129
thread.h
Normal file
129
thread.h
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#ifndef THREAD_H
|
||||||
|
#define THREAD_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include "opencv2/opencv.hpp"
|
||||||
|
#include <QDebug>
|
||||||
|
#include "SapClassBasic.h"
|
||||||
|
#include "camera.h"
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QSemaphore>
|
||||||
|
#include "correct.h"
|
||||||
|
#include <QTcpServer>
|
||||||
|
#include <QTcpSocket>
|
||||||
|
|
||||||
|
//#define REALWIDTH 500
|
||||||
|
//#define READHEIGHT real_height
|
||||||
|
//#define HEIGHT 500
|
||||||
|
|
||||||
|
class QModbusClient;
|
||||||
|
class QModbusReply;
|
||||||
|
|
||||||
|
static int count;
|
||||||
|
|
||||||
|
void onImageDataCallback(SapXferCallbackInfo *pInfo);
|
||||||
|
void onImageCorrectCallback(SapXferCallbackInfo *pInfo);
|
||||||
|
|
||||||
|
class Process_img : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMutex stop_mutex;
|
||||||
|
bool m_stop;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Process_img(QObject *parent = nullptr);
|
||||||
|
void exitThread();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void show_img(cv::Mat);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Adjust_para: public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMutex stop_mutex;
|
||||||
|
bool is_stop;
|
||||||
|
bool correct_flag;
|
||||||
|
QMutex correct_mutex;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Adjust_para(QObject *parent = nullptr);
|
||||||
|
void exitThread();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void send_image_debug(cv::Mat);
|
||||||
|
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void get_correct_signal();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class SendThread: public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SendThread(QObject *parent = NULL);
|
||||||
|
QTcpServer *send_server;
|
||||||
|
QTcpSocket *send_socket;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class RecvThread: public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RecvThread(QObject *parent = NULL);
|
||||||
|
QTcpServer *recv_server;
|
||||||
|
QTcpSocket *recv_socket;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void send_sortingResult(char*);
|
||||||
|
void SendPicInfo(char*);
|
||||||
|
// void read_plc();
|
||||||
|
};
|
||||||
|
|
||||||
|
class RestartThread: public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMutex restr_mutex;
|
||||||
|
bool restr_flag;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void run();
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RestartThread(QObject *parent = NULL);
|
||||||
|
void restr_fun();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // THREAD_H
|
||||||
1054
widget.cpp
Normal file
1054
widget.cpp
Normal file
File diff suppressed because it is too large
Load Diff
109
widget.h
Normal file
109
widget.h
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
#ifndef WIDGET_H
|
||||||
|
#define WIDGET_H
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <QWidget>
|
||||||
|
#include "camera.h"
|
||||||
|
#include "opencv2/opencv.hpp"
|
||||||
|
#include "opencv2/imgproc/types_c.h"
|
||||||
|
#include <QPixmap>
|
||||||
|
#include "correct.h"
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <QVector>
|
||||||
|
#include "showpic.h"
|
||||||
|
|
||||||
|
#pragma comment(lib,"ws2_32.lib")
|
||||||
|
|
||||||
|
class QModbusClient;
|
||||||
|
class QModbusReply;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class Widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Widget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Widget(QWidget *parent = 0);
|
||||||
|
~Widget();
|
||||||
|
void plc_connect();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
//button
|
||||||
|
//Tab_1
|
||||||
|
void btn_Tab1_1_click();
|
||||||
|
void btn_Tab1_2_click();
|
||||||
|
|
||||||
|
//Tab_2
|
||||||
|
void showlabel(cv::Mat);
|
||||||
|
void btn_Tab2_start_click();
|
||||||
|
void btn_Tab2_stop_click();
|
||||||
|
void btn_Tab2_mainMenu_click();
|
||||||
|
void showlabelSorting(char*);
|
||||||
|
void btn_Tab2_autoLearning_click();
|
||||||
|
void btn_Tab2_light_click();
|
||||||
|
void btn_Tab2_middle_click();
|
||||||
|
void btn_Tab2_dark_click();
|
||||||
|
void on_btn_Tab2_Preprocessing_clicked();
|
||||||
|
void on_btn_Tab2_show_clicked();
|
||||||
|
void btn_Tab2_train_click();
|
||||||
|
void showPic(char*);
|
||||||
|
//Tab_3
|
||||||
|
void btn_Tab3_cameraParasettings_click();
|
||||||
|
void btn_Tab3_mainMenu_click();
|
||||||
|
void showimage_test(cv::Mat);
|
||||||
|
void btn_Tab3_saveImg_click();
|
||||||
|
void btn_Tab3_changeModel_click();
|
||||||
|
//Tab_4
|
||||||
|
void btn_Tab4_return_click();
|
||||||
|
void btn_Tab4_getCorrect_click();
|
||||||
|
void btn_Tab4_black_click();
|
||||||
|
void btn_Tab4_white_click();
|
||||||
|
void btn_Tab4_wbcorrect_click();
|
||||||
|
void on_btn_Tab2_start_2_clicked();
|
||||||
|
void on_btn_Tab2_start_3_clicked();
|
||||||
|
void on_btn_Tab2_start_4_clicked();
|
||||||
|
|
||||||
|
void dafei_slot();
|
||||||
|
|
||||||
|
//Tab_5
|
||||||
|
void btn_Tab5_skip_click();
|
||||||
|
void skip_Notime();
|
||||||
|
|
||||||
|
void on_btn_Tab4_exit_clicked();
|
||||||
|
|
||||||
|
//picture
|
||||||
|
void PictureProcess();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::Widget *ui;
|
||||||
|
|
||||||
|
Adjust_para * adjust_para;
|
||||||
|
QPixmap pix;
|
||||||
|
QPixmap pix_test;
|
||||||
|
SendThread *send_thread = nullptr;
|
||||||
|
RecvThread *recv_thread = nullptr;
|
||||||
|
|
||||||
|
QTimer *skip;
|
||||||
|
|
||||||
|
QTimer* dafei = new QTimer;
|
||||||
|
void connect_signals();
|
||||||
|
void init_window();
|
||||||
|
|
||||||
|
RestartThread *restart_thread = nullptr;
|
||||||
|
|
||||||
|
showpic *pic = nullptr;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void correct_signal();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif // WIDGET_H
|
||||||
776
widget.ui
Normal file
776
widget.ui
Normal file
@ -0,0 +1,776 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Widget</class>
|
||||||
|
<widget class="QWidget" name="Widget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1038</width>
|
||||||
|
<height>701</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Widget</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>1041</width>
|
||||||
|
<height>701</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Arial</family>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: rgb(218, 239, 252);</string>
|
||||||
|
</property>
|
||||||
|
<property name="currentIndex">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="tab">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Tab 1</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLabel" name="label_show_welcome">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>200</x>
|
||||||
|
<y>90</y>
|
||||||
|
<width>631</width>
|
||||||
|
<height>121</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Arial</family>
|
||||||
|
<pointsize>72</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color:rgb(0, 0, 0);
|
||||||
|
background-color: rgb(153, 204, 153);
|
||||||
|
border-radius: 50px;</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>木地板分选</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab1_1">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>190</x>
|
||||||
|
<y>440</y>
|
||||||
|
<width>211</width>
|
||||||
|
<height>81</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>36</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(153, 102, 51);
|
||||||
|
border-radius:20px;
|
||||||
|
background-color:rgb(170, 214, 255);
|
||||||
|
border-width:4px; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>分选页面</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab1_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>630</x>
|
||||||
|
<y>440</y>
|
||||||
|
<width>211</width>
|
||||||
|
<height>81</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>36</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(153, 102, 51);
|
||||||
|
border-radius:20px;
|
||||||
|
background-color:rgb(170, 214, 255);
|
||||||
|
border-width:4px; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>详细设置</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_2">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>Tab 2</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLabel" name="showlabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>611</width>
|
||||||
|
<height>431</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: rgb(0, 0, 0);</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_start">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>670</x>
|
||||||
|
<y>498</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>开始</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_stop">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>870</x>
|
||||||
|
<y>498</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>结束</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_mainMenu">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>40</x>
|
||||||
|
<y>498</y>
|
||||||
|
<width>150</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>24</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(238, 238, 236);
|
||||||
|
border-radius:15px;
|
||||||
|
background-color: rgb(136, 138, 133);
|
||||||
|
border-width:4px; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>主菜单</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_showSorting">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>430</y>
|
||||||
|
<width>611</width>
|
||||||
|
<height>51</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Arial</family>
|
||||||
|
<pointsize>33</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color:rgb(0, 0, 0);
|
||||||
|
background-color: rgb(153, 204, 153);
|
||||||
|
border-radius: 50px;</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QGroupBox" name="groupBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>640</x>
|
||||||
|
<y>20</y>
|
||||||
|
<width>381</width>
|
||||||
|
<height>381</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="title">
|
||||||
|
<string>自学习</string>
|
||||||
|
</property>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_autoLearning">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>50</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>自学习</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_light">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>140</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>保存花纹</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_middle">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>220</x>
|
||||||
|
<y>140</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>保存直纹</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_dark">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>230</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>保存深色</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_train">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>220</x>
|
||||||
|
<y>310</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>训练模型</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_Preprocessing">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>220</x>
|
||||||
|
<y>230</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>17</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>图片预处理</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_show">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>310</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>17</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>图片展示</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_start_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>520</x>
|
||||||
|
<y>580</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>light</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_start_3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>670</x>
|
||||||
|
<y>580</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>middle</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab2_start_4">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>820</x>
|
||||||
|
<y>580</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>dark</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_3">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>页</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLabel" name="label_detailedSettings">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>30</y>
|
||||||
|
<width>180</width>
|
||||||
|
<height>58</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>30</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(238, 238, 236);
|
||||||
|
background-color: rgb(204, 0, 0);
|
||||||
|
border-radius:10px;</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>详细设置</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab3_cameraParasettings">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>210</x>
|
||||||
|
<y>140</y>
|
||||||
|
<width>211</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(238, 238, 236);
|
||||||
|
border-radius:10px;
|
||||||
|
background-color: rgb(136, 138, 133);
|
||||||
|
font: 24pt "Ubuntu";
|
||||||
|
border-width:4px; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>相机校正</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab3_mainMenu">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>820</x>
|
||||||
|
<y>560</y>
|
||||||
|
<width>150</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(238, 238, 236);
|
||||||
|
border-radius:10px;
|
||||||
|
background-color: rgb(136, 138, 133);
|
||||||
|
font: 24pt "Ubuntu";
|
||||||
|
border-width:4px; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>主菜单</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab3_saveImg">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>570</x>
|
||||||
|
<y>140</y>
|
||||||
|
<width>211</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(238, 238, 236);
|
||||||
|
border-radius:10px;
|
||||||
|
background-color: rgb(136, 138, 133);
|
||||||
|
font: 24pt "Ubuntu";
|
||||||
|
border-width:4px; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>保存图片</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab3_changeModel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>210</x>
|
||||||
|
<y>260</y>
|
||||||
|
<width>211</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(238, 238, 236);
|
||||||
|
border-radius:10px;
|
||||||
|
background-color: rgb(136, 138, 133);
|
||||||
|
font: 24pt "Ubuntu";
|
||||||
|
border-width:4px; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>切换模型</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_4">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>页</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QPushButton" name="btn_Tab4_return">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>730</x>
|
||||||
|
<y>560</y>
|
||||||
|
<width>261</width>
|
||||||
|
<height>51</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>24</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color: rgb(238, 238, 236);
|
||||||
|
background-color: rgb(136, 138, 133);
|
||||||
|
border-radius:10px;</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>返回</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="showlabel_set">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>591</width>
|
||||||
|
<height>401</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">background-color: rgb(0, 0, 0);</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>TextLabel</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_Tab4_1">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>150</x>
|
||||||
|
<y>530</y>
|
||||||
|
<width>281</width>
|
||||||
|
<height>101</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>17</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>亮度值</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_Tab4_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>250</x>
|
||||||
|
<y>550</y>
|
||||||
|
<width>141</width>
|
||||||
|
<height>71</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab4_black">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>660</x>
|
||||||
|
<y>130</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>黑场采集</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab4_white">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>810</x>
|
||||||
|
<y>130</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>白场采集</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab4_wbcorrect">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>810</x>
|
||||||
|
<y>210</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>黑白校正</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab4_exit">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>310</x>
|
||||||
|
<y>430</y>
|
||||||
|
<width>211</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>停止显示</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab4_getCorrect">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>430</y>
|
||||||
|
<width>211</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>显示图像亮度</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="tab_5">
|
||||||
|
<attribute name="title">
|
||||||
|
<string>页</string>
|
||||||
|
</attribute>
|
||||||
|
<widget class="QLabel" name="label_show_welcome_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>30</x>
|
||||||
|
<y>90</y>
|
||||||
|
<width>971</width>
|
||||||
|
<height>121</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Arial</family>
|
||||||
|
<pointsize>64</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color:rgb(0, 0, 0);
|
||||||
|
background-color: rgb(153, 204, 153);
|
||||||
|
border-radius: 50px;</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>木地板颜色分选系统</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_showSorting_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>270</x>
|
||||||
|
<y>310</y>
|
||||||
|
<width>441</width>
|
||||||
|
<height>51</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Arial</family>
|
||||||
|
<pointsize>33</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">color:rgb(0, 0, 0);
|
||||||
|
background-color: rgb(255, 192, 203);
|
||||||
|
border-radius: 50px;</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>光源预热中...</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QPushButton" name="btn_Tab5_skip">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>840</x>
|
||||||
|
<y>540</y>
|
||||||
|
<width>121</width>
|
||||||
|
<height>61</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>22</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>忽略</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
91
wooden.pro
Normal file
91
wooden.pro
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#-------------------------------------------------
|
||||||
|
#
|
||||||
|
# Project created by QtCreator 2022-03-18T10:12:37
|
||||||
|
#
|
||||||
|
#-------------------------------------------------
|
||||||
|
|
||||||
|
QT += core gui network serialbus serialport
|
||||||
|
|
||||||
|
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||||
|
|
||||||
|
TARGET = wooden
|
||||||
|
TEMPLATE = app
|
||||||
|
|
||||||
|
LIBS += -Ldll -lws2_32
|
||||||
|
|
||||||
|
# The following define makes your compiler emit warnings if you use
|
||||||
|
# any feature of Qt which as been marked as deprecated (the exact warnings
|
||||||
|
# depend on your compiler). Please consult the documentation of the
|
||||||
|
# deprecated API in order to know how to port your code away from it.
|
||||||
|
DEFINES += QT_DEPRECATED_WARNINGS
|
||||||
|
|
||||||
|
# You can also make your code fail to compile if you use deprecated APIs.
|
||||||
|
# In order to do so, uncomment the following line.
|
||||||
|
# You can also select to disable deprecated APIs only up to a certain version of Qt.
|
||||||
|
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
|
||||||
|
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
main.cpp \
|
||||||
|
widget.cpp \
|
||||||
|
camera.cpp \
|
||||||
|
thread.cpp \
|
||||||
|
correct.cpp \
|
||||||
|
src/modbus.c \
|
||||||
|
src/modbus-data.c \
|
||||||
|
src/modbus-rtu.c \
|
||||||
|
src/modbus-tcp.c \
|
||||||
|
showpic.cpp \
|
||||||
|
relistwidget_item.cpp \
|
||||||
|
imagewin.cpp
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
widget.h \
|
||||||
|
camera.h \
|
||||||
|
thread.h \
|
||||||
|
correct.h \
|
||||||
|
src/modbus.h \
|
||||||
|
src/modbus-private.h \
|
||||||
|
src/modbus-rtu.h \
|
||||||
|
src/modbus-rtu-private.h \
|
||||||
|
src/modbus-tcp.h \
|
||||||
|
src/modbus-tcp-private.h \
|
||||||
|
src/modbus-version.h \
|
||||||
|
showpic.h \
|
||||||
|
relistwidget_item.h \
|
||||||
|
imagewin.h
|
||||||
|
|
||||||
|
FORMS += \
|
||||||
|
widget.ui \
|
||||||
|
showpic.ui \
|
||||||
|
imagewin.ui
|
||||||
|
|
||||||
|
#LIBS += -LC:/opencv/build/x64/vc15/lib -lopencv_world453
|
||||||
|
|
||||||
|
#INCLUDEPATH += C:/opencv/build/include \
|
||||||
|
# += C:/opencv/build/include/opencv2
|
||||||
|
|
||||||
|
#LIBS += -LC:/Users/lzy/Downloads/opencv/build/x64/vc15/lib -lopencv_world453
|
||||||
|
|
||||||
|
#INCLUDEPATH += C:/Users/lzy/Downloads/opencv/build/include \
|
||||||
|
# += C:/Users/lzy/Downloads/opencv/build/include/opencv2
|
||||||
|
|
||||||
|
LIBS += -LC:/Users/USER/Downloads/opencv/build/x64/vc15/lib -lopencv_world453
|
||||||
|
|
||||||
|
INCLUDEPATH += C:/Users/USER/Downloads/opencv/build/include \
|
||||||
|
+= C:/Users/USER/Downloads/opencv/build/include/opencv2
|
||||||
|
|
||||||
|
LIBS += -L'C:/Program Files/Teledyne DALSA/Sapera/Lib/Win64' -lSapClassBasic
|
||||||
|
LIBS += -L'C:/Program Files/Teledyne DALSA/Sapera/Lib/Win64' -lcorapi
|
||||||
|
|
||||||
|
INCLUDEPATH += 'C:/Program Files/Teledyne DALSA/Sapera/Include'
|
||||||
|
DEPENDPATH += 'C:/Program Files/Teledyne DALSA/Sapera/Include'
|
||||||
|
INCLUDEPATH += 'C:/Program Files/Teledyne DALSA/Sapera/Classes/Basic'
|
||||||
|
DEPENDPATH += 'C:/Program Files/Teledyne DALSA/Sapera/Classes/Basic'
|
||||||
|
|
||||||
|
DISTFILES += \
|
||||||
|
src/modbus.lib
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
318
wooden.pro.user
Normal file
318
wooden.pro.user
Normal file
@ -0,0 +1,318 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE QtCreatorProject>
|
||||||
|
<!-- Written by QtCreator 4.5.2, 2024-05-15T16:13:05. -->
|
||||||
|
<qtcreator>
|
||||||
|
<data>
|
||||||
|
<variable>EnvironmentId</variable>
|
||||||
|
<value type="QByteArray">{9e31907b-3cc3-479e-b8f2-f24c1d383612}</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||||
|
<value type="int">0</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||||
|
<value type="QString" key="language">Cpp</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||||
|
<value type="QString" key="language">QmlJS</value>
|
||||||
|
<valuemap type="QVariantMap" key="value">
|
||||||
|
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||||
|
</valuemap>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||||
|
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||||
|
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||||
|
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||||
|
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||||
|
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||||
|
<valuemap type="QVariantMap"/>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||||
|
<valuemap type="QVariantMap">
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.9.5 MSVC2017 64bit</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.9.5 MSVC2017 64bit</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.595.win64_msvc2017_64_kit</value>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">1</value>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/USER/Desktop/wood9.3/build-wooden-Desktop_Qt_5_9_5_MSVC2017_64bit-Debug</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||||
|
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清理</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||||
|
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">D:/522/wood_aduiduiduiplus</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||||
|
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">false</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清理</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||||
|
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.2">
|
||||||
|
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">C:/Users/USER/Desktop/wood9.3/build-wooden-Desktop_Qt_5_9_5_MSVC2017_64bit-Profile</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">true</value>
|
||||||
|
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.SeparateDebugInfo">true</value>
|
||||||
|
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">构建</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||||
|
</valuemap>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||||
|
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments"/>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">清理</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||||
|
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||||
|
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Profile</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||||
|
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">3</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||||
|
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">部署</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">在本地部署</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||||
|
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.AggregateTraces">false</value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.FlushEnabled">false</value>
|
||||||
|
<value type="uint" key="Analyzer.QmlProfiler.FlushInterval">1000</value>
|
||||||
|
<value type="QString" key="Analyzer.QmlProfiler.LastTraceFile"></value>
|
||||||
|
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||||
|
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||||
|
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||||
|
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||||
|
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||||
|
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||||
|
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||||
|
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||||
|
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||||
|
<value type="int">0</value>
|
||||||
|
<value type="int">1</value>
|
||||||
|
<value type="int">2</value>
|
||||||
|
<value type="int">3</value>
|
||||||
|
<value type="int">4</value>
|
||||||
|
<value type="int">5</value>
|
||||||
|
<value type="int">6</value>
|
||||||
|
<value type="int">7</value>
|
||||||
|
<value type="int">8</value>
|
||||||
|
<value type="int">9</value>
|
||||||
|
<value type="int">10</value>
|
||||||
|
<value type="int">11</value>
|
||||||
|
<value type="int">12</value>
|
||||||
|
<value type="int">13</value>
|
||||||
|
<value type="int">14</value>
|
||||||
|
</valuelist>
|
||||||
|
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||||
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">wooden</value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:D:/522/wood_aduiduiduiplus/wooden/wooden.pro</value>
|
||||||
|
<value type="bool" key="QmakeProjectManager.QmakeRunConfiguration.UseLibrarySearchPath">true</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments"></value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">wooden.pro</value>
|
||||||
|
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory"></value>
|
||||||
|
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory.default">D:/522/wood_aduiduiduiplus</value>
|
||||||
|
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||||
|
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||||
|
</valuemap>
|
||||||
|
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||||
|
</valuemap>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||||
|
<value type="int">1</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||||
|
<value type="int">18</value>
|
||||||
|
</data>
|
||||||
|
<data>
|
||||||
|
<variable>Version</variable>
|
||||||
|
<value type="int">18</value>
|
||||||
|
</data>
|
||||||
|
</qtcreator>
|
||||||
Loading…
Reference in New Issue
Block a user