阶段备份,SQL逻辑修改,去除配置文件。rpc读取逻辑更改。

This commit is contained in:
2025-08-20 16:57:03 +08:00
parent ff97ea7898
commit 53178ddd9a
43 changed files with 889 additions and 608 deletions
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
+2 -1
View File
@@ -9,7 +9,8 @@
#include <functional>
#pragma execution_character_set("utf-8")
const std::string softwareVersion = "2.0.2";
const std::string euiJsonVersion = "1.0.5";
const std::string euiJsonVersion = "1.0.6";
#define saveImgEnable 1
#define switchToTongYongUi 1 //是否切换到通用UI界面
#define skipLogin 1 //是否跳过登录界面
#define sColor_Blue "51, 56, 69"
+1
View File
@@ -8,6 +8,7 @@ public:
virtual void init(qtFuncBridge*,nlohmann::ordered_json& json) = 0;
virtual void cleanup() = 0;
virtual SQLiteDB* getDatabase() = 0;
virtual bool excuteCliCommandPreset(const QString& uuid) = 0;
};
extern "C" {
+8 -1
View File
@@ -44,7 +44,10 @@ signals:
void pieWidgetAddNG();
void pieWidgetAddOK();
void histogramWidgetAddData(std::vector<std::string>);
void setPlcConnectionError();
void setPlcConnectionOk();
void setCamConnectionError();
void setCamConnectionOk();
///////////////////////////////////////////////
// 切换界面
@@ -68,5 +71,9 @@ signals:
void loadingWindow_clearWarningLog();
//////////////////////////////////////////////////////////////
void reInitConfig();
//排障
void runCommand_addBtn(const QString& btnName, const QString& tip, const QString& uuid);
};
#pragma once
+106 -50
View File
@@ -97,7 +97,20 @@ public:
bool res = query.exec(sql);
return res;
}
std::vector<QString> getTables() {
std::vector<QString> tables;
// 查询所有表名,排除sqlite系统表
QString sql = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%';";
QSqlQuery query(m_db);
if (!query.exec(sql)) {
qDebug() << "getTables failed:" << query.lastError().text();
return tables;
}
while (query.next()) {
tables.push_back(query.value(0).toString());
}
return tables;
}
bool dropTable(const QString& tableName) {
QString sql = QString("DROP TABLE IF EXISTS %1").arg(tableName);
return execute(sql);
@@ -317,7 +330,7 @@ public:
// 记录开始时间
auto start = high_resolution_clock::now();
// 查询表中的所有数据
QString csvFileName = filePath + "/" + tableName + ".csv";
QString csvFileName = filePath;
QString sql = QString("SELECT * FROM \"%1\"").arg(tableName);
QSqlQuery query(m_db);
@@ -444,42 +457,94 @@ public:
//stopAutoExport();
}
std::map<QString, QString>csvAndChartLink;
void addtData(const QString& snCode, const std::map<QString, QVariant>& data) {
std::lock_guard<std::mutex> locker(_mutex);
QString currentProcessCsvName = getCurrentProcessCsvName();
if (currentProcessCsvName != currentProcessCsvNameCache)
if (_db->createTable(currentProcessCsvName, db_InitColumns))
currentProcessCsvNameCache = currentProcessCsvName;
auto res = _db->_search(currentProcessCsvName, {}, { {"条码",snCode} });
if (res.empty() == true)//当前数据为空时查询过去的数据是否为空
{
auto lastRes = _db->_search(getLastProcessCsvName(), {}, { {"条码",snCode} });
if (lastRes.empty() == true)//过去的数据也为空 则视作现在要插入的数据为全新的数据
{
std::map<QString, QVariant> insertData = data;
insertData["条码"] = snCode;
insertData["创建时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
insertData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
_db->_insert(currentProcessCsvName, insertData);
bool addtData(const QString& snCode, const std::map<QString, QVariant>& data) {
try {
if (snCode.isEmpty()) {
qWarning() << "addtData: snCode is empty.";
return false;
}
else//过去的数据不为空 更新到过去的数据上
{
std::map<QString, QVariant> updateData = data;
updateData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
_db->_update(getLastProcessCsvName(), updateData, { {"条码",snCode} });
if (data.empty()) {
qWarning() << "addtData: data is empty.";
return false;
}
std::lock_guard<std::mutex> locker(_mutex);
QString currentProcessCsvName = getCurrentProcessCsvName();
if (currentProcessCsvName != currentProcessCsvNameCache) {
if (!_db->createTable(currentProcessCsvName, db_InitColumns)) {
qWarning() << "addtData: Failed to create table:" << currentProcessCsvName;
return false;
}
currentProcessCsvNameCache = currentProcessCsvName;
}
}
else//当前数据不为空 更新到当前数据上
{
std::map<QString, QVariant> updateData = data;
updateData["修改时间"] = QDateTime::currentDateTime().toString("hh:mm:ss");
_db->_update(getCurrentProcessCsvName(), updateData, { {"条码",snCode} });
}
if (timer.elapsed() > m_intervalMs)
{
exportCsv();
timer.start();
// 获取当前表的所有列名
QSqlQuery colQuery;
QString colSql = QString("PRAGMA table_info(\"%1\")").arg(currentProcessCsvName);
QList<QString> tableColumns;
if (colQuery.exec(colSql)) {
while (colQuery.next()) {
tableColumns.append(colQuery.value(1).toString());
}
}
// 检查 data 中的 key 是否在表结构中,不在则新增列
for (const auto& kv : data) {
if (!tableColumns.contains(kv.first)) {
// 默认新增为 TEXT 类型
if (!_db->addColumn(currentProcessCsvName, kv.first, "TEXT")) {
qWarning() << "addtData: Failed to add column:" << kv.first << "to table:" << currentProcessCsvName;
// 可选择 return false 或继续
}
}
}
auto res = _db->_search(currentProcessCsvName, {}, { {"条码",snCode} });
QString nowTime = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz"); // 精度提升到毫秒
bool opResult = false;
if (res.empty()) {
auto lastRes = _db->_search(getLastProcessCsvName(), {}, { {"条码",snCode} });
if (lastRes.empty()) {
// 插入新数据
std::map<QString, QVariant> insertData = data;
insertData["条码"] = snCode;
insertData["创建时间"] = nowTime;
insertData["修改时间"] = nowTime;
opResult = _db->_insert(currentProcessCsvName, insertData);
if (!opResult) {
qWarning() << "addtData: Insert failed for table:" << currentProcessCsvName << "snCode:" << snCode;
}
} else {
// 更新过去的数据
std::map<QString, QVariant> updateData = data;
updateData["修改时间"] = nowTime;
opResult = _db->_update(getLastProcessCsvName(), updateData, { {"条码",snCode} });
if (!opResult) {
qWarning() << "addtData: Update failed for table:" << getLastProcessCsvName() << "snCode:" << snCode;
}
}
} else {
// 更新当前数据
std::map<QString, QVariant> updateData = data;
updateData["修改时间"] = nowTime;
opResult = _db->_update(getCurrentProcessCsvName(), updateData, { {"条码",snCode} });
if (!opResult) {
qWarning() << "addtData: Update failed for table:" << getCurrentProcessCsvName() << "snCode:" << snCode;
}
}
if (timer.elapsed() > m_intervalMs) {
exportCsv();
timer.start();
}
return opResult;
} catch (const std::exception& ex) {
qCritical() << "addtData: Exception caught:" << ex.what();
return false;
} catch (...) {
qCritical() << "addtData: Unknown exception caught.";
return false;
}
}
bool isNewData(const QString& snCode) {
@@ -528,8 +593,7 @@ private:
// }
// delete _db;
//}
void init(SQLiteDB* database_ptr = nullptr)
{
void init(SQLiteDB* database_ptr = nullptr){
std::lock_guard<std::mutex> locker(_mutex);
if (database_ptr == nullptr)
_db = new SQLiteDB("./sqlDatabse/", "database");
@@ -609,20 +673,12 @@ private:
return (dateStr + "白班"); // 上一班是白班
}
}
//void startAutoExport(int intervalMs = 10000) {
// m_intervalMs = intervalMs;
// m_running = true;
// this->start();
//}
//void stopAutoExport() {
// m_running = false;
// this->wait();
//}
void exportCsv()
{
void exportCsv(){
//std::lock_guard<std::mutex> locker(_mutex);
_db->exportTableToCSV(getLastProcessCsvName(), "./csv/", _mutex);
_db->exportTableToCSV(getCurrentProcessCsvName(), "./csv/", _mutex);
QString name = getLastProcessCsvName();
_db->exportTableToCSV(name, "./csv/"+ name +".csv", _mutex);
name = getCurrentProcessCsvName();
_db->exportTableToCSV(name, "./csv/" + name + ".csv", _mutex);
QString currentProcessCsvName = getCurrentProcessCsvName();
if (currentProcessCsvName != currentProcessCsvNameCache)
if (!_db->createTable(currentProcessCsvName, db_InitColumns)) {
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

+4
View File
@@ -37,6 +37,10 @@
<file>icon/rollback.png</file>
<file>icon/plugin.png</file>
<file>icon/summary_data.png</file>
<file>icon/lan_connection_error.png</file>
<file>icon/lan_connection_ok.png</file>
<file>icon/cam_connection_error.png</file>
<file>icon/cam_connection_ok.png</file>
</qresource>
<qresource prefix="/TongYongUiIcon">
<file>TongYongUiIcon/0.cameraModule.png</file>
+98 -28
View File
@@ -61,8 +61,8 @@ bool rpc_finsTcp::readData(std::vector<cv::Mat>& vec_mat, QByteArray& data)
ptr = new JsonRpcClient("127.0.0.1", 9000);
read_JsonRpcClient[data] = ptr;
}
auto result = read_JsonRpcClient[data]->call("excuteCli", QJsonArray{QString(data)}, "finstcp");
data = variantListToByteArray(result);
// auto result = read_JsonRpcClient[data]->call("excuteCli", QJsonArray{QString(data)}, "finstcp");
data = ptr->finsReadCall("excuteCli", QString(data), "finstcp");
return true;
}
bool ifRetryCMD = false;
@@ -219,52 +219,122 @@ bool JsonRpcClient::reconnect() {
return false;
}
}
QVariant jsonToVariant(const nlohmann::json& j)
{
if (j.is_null()) return QVariant();
if (j.is_boolean()) return j.get<bool>();
if (j.is_number_integer()) return j.get<qint64>();
if (j.is_number_unsigned()) return static_cast<quint64>(j.get<std::uint64_t>());
if (j.is_number_float()) return j.get<double>();
if (j.is_string()) return QString::fromStdString(j.get<std::string>());
QVariant JsonRpcClient::call(const QString& method, const QJsonArray& params, const QString& module) {
QMutexLocker locker(&mutex_); // 确保线程安全
if (j.is_array()) {
QVariantList list;
for (const auto& el : j) list.append(jsonToVariant(el));
return list;
}
if (j.is_object()) {
QVariantMap map;
for (auto it = j.begin(); it != j.end(); ++it)
map[QString::fromStdString(it.key())] = jsonToVariant(it.value());
return map;
}
return QVariant(); // fallback
}
QVariant JsonRpcClient::call(const QString& method, const QJsonArray& params, const QString& module)
{
QMutexLocker locker(&mutex_);
if (socket_.state() != QAbstractSocket::ConnectedState) {
qWarning() << "[JsonRpcClient] Socket not connected, trying to reconnect...";
qWarning() << "[JsonRpcClient] Socket not connected.";
if (!reconnect()) return QVariant();
}
QJsonObject request{
{"jsonrpc", "2.0"},
{"method", method},
{"params", params},
{"id", idCounter_++}
};
QString reqStr = QString(R"({"jsonrpc":"2.0","method":"%1","params":%2,"id":%3)")
.arg(method)
.arg(QString::fromUtf8(QJsonDocument(params).toJson(QJsonDocument::Compact)))
.arg(idCounter_++);
if (!module.isEmpty()) {
request["module"] = module;
reqStr += QString(R"(,"module":"%1")").arg(module);
}
reqStr += "}";
QJsonDocument doc(request);
QByteArray data = doc.toJson(QJsonDocument::Compact);
if (socket_.write(data) == -1 || !socket_.waitForBytesWritten(1000)) {
qWarning() << "[JsonRpcClient] Write failed:" << socket_.errorString();
if (socket_.write(reqStr.toUtf8()) == -1 || !socket_.waitForBytesWritten(1000)) {
qWarning() << "[JsonRpcClient] Write failed.";
return QVariant();
}
if (!socket_.waitForReadyRead(3000)) {
qWarning() << "[JsonRpcClient] No response received:" << socket_.errorString();
if (!socket_.waitForReadyRead(10000)) {
qWarning() << "[JsonRpcClient] Read timeout.";
return QVariant();
}
QByteArray responseData = socket_.readAll();
QJsonParseError parseError;
QJsonDocument respDoc = QJsonDocument::fromJson(responseData, &parseError);
if (parseError.error != QJsonParseError::NoError) {
qWarning() << "[JsonRpcClient] JSON parse error:" << parseError.errorString();
// 使用 nlohmann json 替代 Qt 解析
try {
auto respJson = nlohmann::json::parse(responseData.constData(), responseData.constData() + responseData.size());
if (respJson.contains("error")) {
qWarning() << "[JsonRpcClient] Error:" << QString::fromStdString(respJson["error"].dump());
return QVariant();
}
return jsonToVariant(respJson["result"]);
}
catch (const nlohmann::json::parse_error& e) {
qWarning() << "[JsonRpcClient] Parse error:" << e.what();
return QVariant();
}
}
QByteArray JsonRpcClient::finsReadCall(const QString& method, const QString& params, const QString& module) {
QMutexLocker locker(&mutex_);
if (socket_.state() != QAbstractSocket::ConnectedState) {
qWarning() << "[JsonRpcClient] Socket not connected.";
if (!reconnect()) return QByteArray();
}
QJsonObject resp = respDoc.object();
if (resp.contains("error")) {
qWarning() << "[JsonRpcClient] JSON-RPC error:" << resp["error"];
return QVariant();
QString reqStr = QString(R"({"jsonrpc":"2.0","method":"%1","params":["%2"],"id":%3)")
.arg(method)
.arg(params)
.arg(idCounter_++);
if (!module.isEmpty()) {
reqStr += QString(R"(,"module":"%1")").arg(module);
}
reqStr += "}";
if (socket_.write(reqStr.toUtf8()) == -1 || !socket_.waitForBytesWritten(1000)) {
qWarning() << "[JsonRpcClient] Write failed.";
return QByteArray();
}
if (!socket_.waitForReadyRead(10000)) {
qWarning() << "[JsonRpcClient] Read timeout.";
return QByteArray();
}
QByteArray responseData = socket_.readAll();
// 使用 nlohmann json 替代 Qt 解析
try {
if (responseData.contains("error")) {
//qWarning() << "[JsonRpcClient] Error:" << QString::fromStdString(respJson["error"].dump());
return QByteArray();
}
int startPos = responseData.indexOf(": [") + 3;
int length = responseData.indexOf("],") - startPos;
auto splitResult = responseData.mid(startPos, length);
QByteArray result;
for (int i = 0; i < splitResult.size(); i+=3) {
result.append(splitResult[i] -48);
}
return result;
}
catch (const nlohmann::json::parse_error& e) {
qWarning() << "[JsonRpcClient] Parse error:" << e.what();
return QByteArray();
}
return resp["result"].toVariant();
}
void JsonRpcClient::writeCall(const QString& method, const QJsonArray& params, const QString& module) {
if (socket_.state() != QAbstractSocket::ConnectedState) {
+2
View File
@@ -20,6 +20,7 @@
#include <QHostAddress>
#include <qmap.h>
#include <qthread.h>
#include <nlohmannJson.hpp>
enum connectionStatus {
None,
Disconnected,
@@ -32,6 +33,7 @@ public:
JsonRpcClient(const QString& host = "127.0.0.1", quint16 port = 9000);
void writeCall(const QString& method, const QJsonArray& params = {}, const QString& module = QString());
QVariant call(const QString& method, const QJsonArray& params = {}, const QString& module = QString());
QByteArray finsReadCall(const QString& method, const QString& params = "", const QString& module = QString());
bool reconnect(); // 主动重连,或 call() 失败时调用
private:
-16
View File
@@ -5,22 +5,6 @@
typedef dsModuleBase* (*CreateFunction)();
typedef void (*ReleaseFunction)(dsModuleBase* animal);
struct correctionStruct
{
std::vector<double> in_X_X0Y;
std::vector<double> in_Y_X0Y;
std::vector<double> in_Z_X0Y;
std::vector<double> in_Z_X0Y_Value;
std::vector<double> in_X_X0Z;
std::vector<double> in_Y_X0Z;;
std::vector<double> in_Z_X0Z;
std::vector<double> in_Y_X0Z_Value;
std::vector<double> in_X_Y0Z;
std::vector<double> in_Y_Y0Z;
std::vector<double> in_Z_Y0Z;
std::vector<double> in_X_Y0Z_Value;
};
typedef struct {
QString m_stationKy;
QString key; // 相机名称
+30 -25
View File
@@ -8,7 +8,10 @@
#include <handleAiModel.h>
#include <summaryData.h>
#include <quuid.h>
enum saveMode {
basic,
oneFile
};
//所有检测需要的数据均放在这里
class camera;
class detData;
@@ -16,8 +19,7 @@ class detDataManager;
class triggerManager;
using resultHandleCallback = std::function<void(std::shared_ptr <detData>)>;
using algoEvaluateCallback = std::function<bool(std::shared_ptr <detData>,handleAiModelManager*)>;
class detData
{
class detData{
public:
@@ -48,6 +50,8 @@ public:
triggerManager* triggerPtr = nullptr;//触发器指针 一般为plc模块指针
#pragma endregion
#pragma region 存图相关
saveMode _saveMode = saveMode::basic;
QString saveObjectName = "";//存图项目名 用于与其他检测项目区分开
QMutex resultMutex;//结果图锁
std::vector<cv::Mat> resultImgs;//结果图容器
std::vector<cv::Mat> segOriginImgs;//seg检测原图容器
@@ -57,12 +61,14 @@ public:
std::vector<cv::Mat> oriImgs;//原图容器
std::vector<std::string> oriFormat;//原图格式 如果数量不一致直接全存bmp
std::vector<std::string> imgSaveNameParameter;//命名规则 str1_str2... 第一个参数已默认为相机名,在构造函数
void customSaveParam(QString saveObjectNameIN, saveMode _saveModeIN, std::vector<std::string> imgSaveNameParameterIN) {
saveObjectName = saveObjectNameIN;
_saveMode = _saveModeIN;
imgSaveNameParameter.insert(imgSaveNameParameter.end(),imgSaveNameParameterIN.begin(), imgSaveNameParameterIN.end());
}
#pragma endregion
QMap<QString, QVariant> additional;
detData(std::string IN_cameraKeyName) {
cameraKeyName = IN_cameraKeyName;
imgSaveNameParameter.push_back(cameraKeyName);
}
detData() {}
~detData() {
for (auto& img : oriImgs)
img.release();
@@ -74,8 +80,7 @@ public:
img.second.release();
}
};
class detDataManager
{
class detDataManager{
public:
detDataManager(triggerManager* in_triggerManager)
:_triggerManager(in_triggerManager){
@@ -84,18 +89,14 @@ public:
std::unordered_map<QString, std::shared_ptr<detData>>map;
QMutex dataMutex;
std::shared_ptr <detData> createDetData(
QString IN_cameraKeyName,
std::string IN_SN,int imgAmountMin,
std::vector<std::string> oriFormat){
std::shared_ptr <detData> createDetData(QString IN_cameraKeyName,std::string IN_SN, int imgAmountMin,std::vector<std::string> oriFormat) {
QMutexLocker locker(&dataMutex);
std::shared_ptr <detData>dataPtr(new detData(IN_cameraKeyName.toStdString()));
std::shared_ptr <detData>dataPtr(new detData());
dataPtr->cameraKeyName = IN_cameraKeyName.toStdString();
dataPtr->imgSaveNameParameter.push_back(IN_cameraKeyName.toStdString());
dataPtr->oriFormat = oriFormat;
dataPtr->triggerPtr = _triggerManager;
dataPtr->SNcode = IN_SN;
//dataPtr->registerResultHandleCallback(resultSolver);
//dataPtr->registerAlgoEvaluateCallback(_algoEvaluateCallback);
dataPtr->imgAmountMin = imgAmountMin;
dataPtr->dManager = this;
@@ -105,22 +106,26 @@ public:
qDebug() << "创建新容器失败";
return dataPtr;
}
std::shared_ptr <detData> getDetData(QString uuid)
{
std::shared_ptr <detData> createDetData() {
QMutexLocker locker(&dataMutex);
std::shared_ptr <detData>dataPtr(new detData());
map.insert({ dataPtr->uuid,dataPtr });
if (dataPtr == nullptr)
qDebug() << "创建新容器失败";
return dataPtr;
}
std::shared_ptr <detData> getDetData(QString uuid){
QMutexLocker locker(&dataMutex);
auto it = map.find(uuid);
if (it != map.end())
{
if (it != map.end()) {
return it->second;
}
return nullptr;
}
bool deleteDetData(QString uuid)
{
bool deleteDetData(QString uuid) {
QMutexLocker locker(&dataMutex);
auto it = map.find(uuid);
if (it != map.end())
{
if (it != map.end()) {
map.erase(it);
return true;
}
+44 -53
View File
@@ -4,7 +4,7 @@
#include <qdatetime.h>
#include <backStruct.h>
#include <detData.h>
#define saveImgEnable 1
enum imgSaveThreadType
{
oriImg,
@@ -107,55 +107,48 @@ public:
path = pathIn;
}
imgSaveThread saveThread;
QString genDirName(std::shared_ptr <detData> data, imgSaveThreadType type) {
//sqlTableDatas sqlRes = sql->selectSingleData("saveHour", data->SNcode);//查找之前的数据
//获取关键数据
QString imgSaveDirStr = path;//所有图片的路径 sample "D://CCD"
QString imgTypeDirStr;//二级目录,图片类型决定 sample "Result"
QString dateDirStr;//三级目录,日期决定 sample"2024-6-8"
QString hourDirStr;//四级目录,小时段决定 sample "14H"
QString okNgStr;//五级目录,OK/NG决定 sample "OK"
QString detailNameStr;//六级目录 主要是SN,如没有sn则可能是相机名称
#pragma region 赋值
//imgTypeDirStr
switch (type)
{
case oriImg:
imgTypeDirStr = "原图";
break;
case resImg:
imgTypeDirStr = "结果图";
break;
default:
imgTypeDirStr = "error";
}
QString genDirName(std::shared_ptr<detData> data, imgSaveThreadType type, saveMode mode){
// 一级目录(根路径)
const QString basePath = path;
// 二级目录(图片类型)
static const QMap<imgSaveThreadType, QString> typeMap{
{ oriImg, "原图" },
{ resImg, "结果图" }
};
QString imgTypeDir = typeMap.value(type, "error");
// 日期与小时
QDateTime now = QDateTime::currentDateTime();
QString dateDir = now.toString("yyyy-MM-dd");
QString hourDir = QString("%1H").arg(now.time().hour());
// 检测结果
QString resultDir;
if (!data->aiDetOK && !data->halconOK) resultDir = "NG";
else if (!data->aiDetOK) resultDir = "aiNG";
else if (!data->halconOK) resultDir = "halconNG";
else resultDir = "OK";
if (mode == oneFile) {
{
QDateTime currentDateTime = QDateTime::currentDateTime();
dateDirStr = currentDateTime.toString("yyyy-MM-dd");
hourDirStr = QString::number(currentDateTime.time().hour()) + "H//";
}
if(data->aiDetOK == false && data->halconOK == false)
okNgStr = "NG";
else if (data->aiDetOK == false)
okNgStr = "aiNG";
else if (data->halconOK == false)
okNgStr = "halconNG";
else
okNgStr = "OK";
//detailNameStr
if (data->SNcode.length() != 0 && data->SNcode.length() < 50)
detailNameStr = QString::fromStdString(data->SNcode);
else
detailNameStr = QString::fromStdString(data->cameraKeyName);
#pragma endregion
return QString(imgSaveDirStr + "/" +
imgTypeDirStr + "/" +
dateDirStr + "/" +
hourDirStr + "/" +
okNgStr + "/" +
detailNameStr + "/");
// SN 或相机名
QString detailName = (data->SNcode.size() > 0 && data->SNcode.size() < 50)
? QString::fromStdString(data->SNcode)
: QString::fromStdString(data->cameraKeyName);
// 拼接路径
QDir dir(basePath);
dir = QDir(dir.filePath(imgTypeDir));
dir = QDir(dir.filePath(dateDir));
dir = QDir(dir.filePath(hourDir));
dir = QDir(dir.filePath(resultDir));
dir = QDir(dir.filePath(detailName));
return dir.path() + "/";
}
std::vector<std::string> genFileNames(std::shared_ptr <detData> data, imgSaveThreadType type, std::string format = "")
{
std::vector<std::string> resultFileNames;
@@ -193,9 +186,8 @@ public:
return resultFileNames;
}
void saveOri(std::shared_ptr <detData> data)
{
QString fileSavePath = genDirName(data, oriImg);//获取文件夹名
void saveOri(std::shared_ptr <detData> data) {
QString fileSavePath = genDirName(data, oriImg, data->_saveMode);//获取文件夹名
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
std::vector<std::string>fileNames = genFileNames(data, oriImg);
@@ -205,9 +197,8 @@ public:
if (queueSize > 10)
qDebug() << "queueSize " << queueSize;
}
void saveRes(std::shared_ptr <detData> data)
{
QString fileSavePath = genDirName(data, resImg);//获取文件夹名
void saveRes(std::shared_ptr <detData> data){
QString fileSavePath = genDirName(data, resImg,data->_saveMode);//获取文件夹名
createDirectoryIfNotExists(fileSavePath);//不存在此文件夹则创建
//结果图保存
std::vector<std::string>resFileNames = genFileNames(data, resImg);
+22 -7
View File
@@ -25,6 +25,8 @@ triggerManager::triggerManager(detProcess* _detProcessIn, qtFuncBridge* bridgeIn
triggerFileName = QString::fromStdString(triggerJson["moduleName"]);
IpAndPort = QString::fromStdString(triggerJson["initStr"]);
heartBeatIntervalMS = triggerJson["heartBeatIntervalMS"];
sleepIntervalMS = triggerJson["sleepIntervalMS"];
std::vector<std::string> heartbeats = triggerJson["heartBeatCmd"];
for (auto& cmd : heartbeats) {
heartBeatCmds.push_back(QString::fromStdString(cmd));
@@ -34,18 +36,16 @@ void triggerManager::run(){
if(connectHost() == false)
return;
QThread::msleep(1000);
int cnt = 0;
QElapsedTimer heartTimer;
while (runFlag){
reciveCommond();
QThread::msleep(10);
QThread::msleep(sleepIntervalMS);
//心跳
cnt++;
if (cnt > 100) {
if (heartTimer.elapsed()> heartBeatIntervalMS) {
sendFinsMsg(heartBeatCmds[heartBeatCmdCnt++]);
if(heartBeatCmdCnt >= heartBeatCmds.size())
heartBeatCmdCnt = 0;
cnt = 0;
// qDebug() << "heartbeat";
heartTimer.start();
}
}
@@ -133,8 +133,23 @@ void triggerManager::decodeCameraCMD(readAllStruct& _struct, QByteArray byte)
{
if (byte.isEmpty())
{
qCritical() << "ERROR:cant read data from Fins,无法从fins读取数据";
if (isConnected == true) {
lostConnectionCountTimer.start();
std::cout<< "与PLC的连接已断开,正在尝试重连" << std::endl;
}
if (lostConnectionRePrintTimer.elapsed() > 1000) {
qCritical() << "ERROR:cant read data from Fins,无法从fins读取数据";
emit bridge->setPlcConnectionError();
isConnected = false;
lostConnectionRePrintTimer.start();
}
return;
}
else if (isConnected == false) {
emit bridge->setPlcConnectionOk();
isConnected = true;
qDebug() << "掉线时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒";
std::cout << "重连成功,经过时间:" << lostConnectionCountTimer.elapsed() / 1000.0 << "秒" << std::endl;
}
checkCallbackAndTrigger(_struct,byte);
}
+55 -54
View File
@@ -7,6 +7,7 @@
#include <functional>
#include <serviceModule.h>
#include <nlohmannJson.hpp>
#include <qelapsedtimer.h>
#define switchToRpc 1
#define debugTesting 0
@@ -19,33 +20,32 @@ class detProcess;
//防止重复触发
class triggerLockerT {
public:
triggerLockerT() {}
~triggerLockerT() {
lockerList.clear();
// 不存在则返回true
bool checkLocker(int pos) const {
return lockerVec.find(pos) == lockerVec.end();
}
bool checkLocker(int pos) {
for (auto& it : lockerList) {
if (it == pos) {
return false;
}
}
return true;
}
void reFreshLocker(QByteArray& input) {
if (input.size() == 0)return;
for (auto& it : lockerList) {
if (input.at(it) == 0) {
lockerList.erase(std::remove(lockerList.begin(), lockerList.end(), it), lockerList.end());
}
}
}
void adddLocker(int pos) {
lockerList.push_back(pos);
}
std::vector<int>lockerList;
private:
// 如果和加锁的值不同则删除
void reFreshLocker(const QByteArray& input) {
for (auto it = lockerVec.begin(); it != lockerVec.end(); ) {
if (it->first >= input.size() || input.at(it->first) != it->second) {
it = lockerVec.erase(it); // erase 返回下一个迭代器
}
else {
++it;
}
}
}
// 添加锁
void addLocker(int pos, int val) {
lockerVec[pos] = val;
}
private:
std::unordered_map<int, int> lockerVec;
};
//触发器类 fins触发 tcp触发等 替代myiothread
class triggerManager : public serviceModule
{
@@ -61,8 +61,7 @@ public:
QString triggerFileName;
QString IpAndPort;
QString triggerInitStr;
~triggerManager()
{
~triggerManager(){
runFlag = false;
this->stop();
this->terminate();
@@ -71,8 +70,7 @@ public:
triggerManager(detProcess*, qtFuncBridge* bridgeIn, nlohmann::ordered_json& triggerJson);
bool connectHost();
void run();
void stop()
{
void stop(){
runFlag = false;
this->terminate();
}
@@ -206,15 +204,13 @@ public:
#pragma endregion
//CALL BACK
struct triggerCallbackStruct
{
struct triggerCallbackStruct{
int triggerAddress;
int triggerValue;
triggerCallback func;
std::string funcName;
};
bool registerCallback(int triggerAddress, int triggerValue, triggerCallback func, std::string funcName ="")
{
bool registerCallback(int triggerAddress, int triggerValue, triggerCallback func, std::string funcName =""){
triggerCallbackStruct _triggerCallbackStruct;
_triggerCallbackStruct.triggerAddress = triggerAddress;
_triggerCallbackStruct.triggerValue = triggerValue;
@@ -230,8 +226,7 @@ public:
return false;
}
std::map<QByteArray, std::vector<triggerCallbackStruct>> triggerCallbackFuncs;
void checkCallbackAndTrigger(readAllStruct& _struct,QByteArray & byteArray)//检查是否符合回调函数的触发条件
{
void checkCallbackAndTrigger(readAllStruct& _struct,QByteArray & byteArray){//检查是否符合回调函数的触发条件
for (auto callback : triggerCallbackFuncs[_struct.readAllCmd])
{
if (checkTrigger(callback.triggerAddress, callback.triggerValue, _struct, byteArray) == true)
@@ -249,8 +244,7 @@ public:
}
}
std::string readSnFromQByteArray(QByteArray plcByte, int dmPos,
bool highLowConversion, bool clearAfterRead, int Size)
{
bool highLowConversion, bool clearAfterRead, int Size){
int startPos = 0;
for (auto& _struct : readAllCmds) {
if (dmPos > _struct.startPos &&
@@ -262,8 +256,7 @@ public:
return "ERROR_OUT_OF_RANGE";
}
int triggerPos = (dmPos - startPos) * 2;
if (triggerPos < 0)
{
if (triggerPos < 0){
std::cout << "Read SN error,trigger is DM:" << dmPos << ",but read start at DM:" << startPos << endl;
return "snErrorsnError" + getCurrentDateTime();
}
@@ -271,20 +264,16 @@ public:
if (plcByte.at(triggerPos + 1) == 0 && plcByte.at(triggerPos) == 0)
return "snErrorsnError" + getCurrentDateTime();
int snCount = 0;
if (highLowConversion == true)
{
while (plcByte.at(snCount + triggerPos) != 0 || plcByte.at(snCount + triggerPos + 1) != 0)
{
if (highLowConversion == true){
while (plcByte.at(snCount + triggerPos) != 0 || plcByte.at(snCount + triggerPos + 1) != 0){
if (plcByte.at(snCount + triggerPos) != 0)
str += QChar(plcByte.at(snCount + triggerPos));
snCount++;
}
}
else
{
while (plcByte.at(snCount + triggerPos) != 0 || plcByte.at(snCount + triggerPos + 1) != 0)
{
else{
while (plcByte.at(snCount + triggerPos) != 0 || plcByte.at(snCount + triggerPos + 1) != 0){
if (plcByte.at(snCount + triggerPos + 1) != 0)
str += QChar(plcByte.at(snCount + triggerPos + 1));
@@ -303,6 +292,7 @@ public:
}
private:
QElapsedTimer lostConnectionCountTimer,lostConnectionRePrintTimer;
qtFuncBridge* bridge;
bool libLoadedflag = false;
QLibrary* m_lib = nullptr;
@@ -319,25 +309,34 @@ private:
/// <param name="value">值</param>
/// <param name="byte">QByteArray</param>
/// <returns></returns>
bool checkTrigger(int dmPos, int value, readAllStruct& _struct, QByteArray& byte, bool lockerDisable = false)
{
bool checkTrigger(int dmPos, int value, readAllStruct& _struct, QByteArray& byte, bool lockerDisable = false){
int triggerPos = (dmPos - _struct.startPos) * 2 + 1;
if (byte.size() < triggerPos)
return false;
if (byte.at(triggerPos) == value)
{
if (byte.at(triggerPos) == value){
if (tLocker[_struct.readAllCmd].checkLocker(triggerPos) == false)
return false;
if (lockerDisable == false)
tLocker[_struct.readAllCmd].adddLocker(triggerPos);
tLocker[_struct.readAllCmd].addLocker(triggerPos, value);
return true;
}
else
return false;
}
bool checkTrigger_Unsafe(int dmPos, int value, readAllStruct& _struct, QByteArray& byte, bool lockerDisable = false) {
int triggerPos = (dmPos - _struct.startPos) * 2 + 1;
if (byte.at(triggerPos) == value) {
if (tLocker[_struct.readAllCmd].checkLocker(triggerPos) == false)
return false;
if (lockerDisable == false)
tLocker[_struct.readAllCmd].addLocker(triggerPos, value);
return true;
}
else
return false;
}
//接受数据
bool reciveFinsMsg(QByteArray& readByte)
{
bool reciveFinsMsg(QByteArray& readByte){
if (!trigger->readData(vec_mat, readByte))
{
qCritical() << "[TCP] " << " finstcp_ptr readData error!";
@@ -349,7 +348,8 @@ private:
//解析并触发
void decodeCameraCMD(readAllStruct&,QByteArray byte);
//触发器的配置
int interval = 50;//间隔
int sleepIntervalMS = 50;//间隔
int heartBeatIntervalMS = 800;
int heartBeatCmdCnt = 0;
std::vector<QString> heartBeatCmds;
#if switchToRpc==0
@@ -359,6 +359,7 @@ private:
ReleaseRpcModuleBaseFunction destory_finstcp; //释放
rpcModuleBase* trigger = nullptr;
#endif
bool isConnected = true;
bool runFlag = true;
bool init = false;
std::vector<cv::Mat> vec_mat;//没啥用,一直保持为空就好
+3
View File
@@ -28,6 +28,9 @@ public:
SQLiteDB* getDatabase() {
return _detProcess->dataBase;
}
bool excuteCliCommandPreset(const QString& uuid) {
return _detProcess->_cliManager->excutePreset(uuid);
}
private:
bool initOnce = false;
detProcess* _detProcess;
+6 -3
View File
@@ -11,9 +11,10 @@ public:
CsvWriter* _csvWriter = nullptr;
missonResultHandle* _missonResultHandle = nullptr;
ServiceManager _serviceManager;
CLIManager* _cliManager; // 命令行接口管理器
bool initOnce = false;
detProcess():_cliManager(&_serviceManager){
dataBase = new SQLiteDB("./DataBase/", "eui_db");
detProcess(){
dataBase = new SQLiteDB("./sqlDatabse/", "eui_db");
_csvWriter = new CsvWriter(dataBase);
}
@@ -33,6 +34,7 @@ public:
_serviceManager._csvWriter = _csvWriter;
_serviceManager._handleAiModelManager = new handleAiModelManager(jsonIn, bridgeIn);
connect(bridgeIn, &qtFuncBridge::reInitConfig, this, [=]() {reinitConfig(); });
_cliManager = new CLIManager(&_serviceManager, bridgeIn);
}
}
@@ -88,6 +90,7 @@ public:
json["missionSettings"],
dataBase, bridge
);
_cliManager->initBasicPreset();
//_threadManager->registerResultHandleCallback(
// [this](std::shared_ptr<detData> data) {
// detectionResultHandle(data);
@@ -110,7 +113,7 @@ private:
nlohmann::ordered_json json;
qtFuncBridge* bridge;
MissionLoader _missionLoader; // 任务加载器,用于加载任务配置
CLIManager _cliManager; // 命令行接口管理器
};
#pragma once
+118 -66
View File
@@ -23,79 +23,131 @@ private:
class CLIManager {
public:
CLIManager(ServiceManager* _serviceManagerIn):_serviceManager(_serviceManagerIn){}
CLIManager(ServiceManager* _serviceManagerIn,qtFuncBridge* bridgeIn)
:_serviceManager(_serviceManagerIn), bridge(bridgeIn) {}
~CLIManager() {}
void cliCommands(const std::string& command,std::vector<QVariant>args) {
auto it = commandMap.find(command);
if (it != commandMap.end()) {
switch (it->second) {
case Trigger:
trigger(args);
break;
case Evaluate:
evaluate(args);
break;
default:
break;
#pragma region trash
// void cliCommands(const std::string& command,std::vector<QVariant>args) {
// auto it = commandMap.find(command);
// if (it != commandMap.end()) {
// switch (it->second) {
// case Trigger:
// trigger(args);
// break;
// case Evaluate:
// evaluate(args);
// break;
// default:
// break;
// }
// } else {
// std::cerr << "Unknown command: " << command << std::endl;
// }
// }
// void trigger(std::vector<QVariant>&args) {
// try {
//#pragma region 错误检查
// if (_serviceManager->_triggerManager == nullptr) {
// std::cerr << "Trigger manager is not initialized." << std::endl;
// return;
// }
// if (args.size() < 1) {
// std::cerr << "Insufficient arguments for trigger command." << std::endl;
// return;
// }
// if (args[0].type() != QVariant::String) {
// std::cerr << "Invalid argument type for trigger command." << std::endl;
// return;
// }
//
//#pragma endregion
// if (args[0].toString() == "write" && args.size() >= 3) {
// bool result = _serviceManager->_triggerManager->sendFinsMsg(
// QString("write_" + args[1].toString() + "_"
// + args[2].toString()
// ));
// if (!result)
// std::cerr << "Failed to send write command." << std::endl;
// else
// std::cout << "Write command sent successfully." << std::endl;
// return;
// }
// else if (args[0].toString() == "read" && args.size() >= 2) {
// QVariant result = _serviceManager->_triggerManager->read(args[1].toInt());
// if (result.isValid()) {
// std::cout << "Read command result: " << result.toString().toStdString() << std::endl;
// }
// else {
// std::cerr << "Failed to read data." << std::endl;
// }
// }
// }
// catch(const std::exception& e) {
// std::cerr << "Error in trigger command: " << e.what() << std::endl;
// }
// catch (...) {
// std::cerr << "Unknown error occurred in trigger command." << std::endl;
// }
// }
// void evaluate(std::vector<QVariant>&args) {
//#pragma region 处理错误
// //if()
//#pragma endregion
//
// }
#pragma endregion
bool cliCommand(const QString& command) {
auto strList = command.split("#");
if (strList[0] == "fins") {
_serviceManager->_triggerManager->sendFinsMsg(strList[1]);
return true;
}
else if (strList[0] == "reconfig") {
return true;
}
else if (strList[0] == "waitMs") {
QThread::msleep(strList[1].toInt());
return true;
}
std::cout << "命令未定义!" << command.toStdString() << std::endl;
return false;
}
bool excutePreset(const QString& uuid) {
auto commands = presets[uuid];
std::thread([this,commands] {for (auto& command : commands)cliCommand(command); }).detach();
return true;
}
void addPreset(const QString& btnName, QStringList commands) {
presets[btnName] = commands;
}
void initBasicPreset() {
for (auto& data : _serviceManager->_triggerManager->triggerCallbackFuncs) {
for (auto& callbacks : data.second) {
QString uuid = QUuid::createUuid().toString();;
auto commands = basicTriggerPresetGenerate(callbacks.triggerAddress);
QString tips;
for(auto& cmd : commands) {
tips += cmd + "\n";
}
emit bridge->runCommand_addBtn(
QString::fromStdString(callbacks.funcName),tips,uuid);
presets[uuid] = commands;
}
} else {
std::cerr << "Unknown command: " << command << std::endl;
}
}
void trigger(std::vector<QVariant>&args) {
try {
#pragma region 错误检查
if (_serviceManager->_triggerManager == nullptr) {
std::cerr << "Trigger manager is not initialized." << std::endl;
return;
}
if (args.size() < 1) {
std::cerr << "Insufficient arguments for trigger command." << std::endl;
return;
}
if (args[0].type() != QVariant::String) {
std::cerr << "Invalid argument type for trigger command." << std::endl;
return;
}
#pragma endregion
if (args[0].toString() == "write" && args.size() >= 3) {
bool result = _serviceManager->_triggerManager->sendFinsMsg(
QString("write_" + args[1].toString() + "_"
+ args[2].toString()
));
if (!result)
std::cerr << "Failed to send write command." << std::endl;
else
std::cout << "Write command sent successfully." << std::endl;
return;
}
else if (args[0].toString() == "read" && args.size() >= 2) {
QVariant result = _serviceManager->_triggerManager->read(args[1].toInt());
if (result.isValid()) {
std::cout << "Read command result: " << result.toString().toStdString() << std::endl;
}
else {
std::cerr << "Failed to read data." << std::endl;
}
}
}
catch(const std::exception& e) {
std::cerr << "Error in trigger command: " << e.what() << std::endl;
}
catch (...) {
std::cerr << "Unknown error occurred in trigger command." << std::endl;
}
}
void evaluate(std::vector<QVariant>&args) {
#pragma region 处理错误
//if()
#pragma endregion
QStringList basicTriggerPresetGenerate(int& triggerAddress) {
QString triggerAddressStr = QString::number(triggerAddress);
return {
"fins#write_short_"+ triggerAddressStr +"_1",
"waitMs#500",
"fins#write_short_" + triggerAddressStr + "_0",
};
}
private:
qtFuncBridge* bridge;
QMap<QString, QStringList> presets;
ServiceManager* _serviceManager;
enum CommandType {
Trigger,
Binary file not shown.
@@ -14,6 +14,7 @@
#include <uiModule/uiModule_histogramWidget.h>
#include <uiModule/uiModule_userSwitch.h>
#include <uiModule/uiModule_softwareDataDisplay.h>
#include <uiModule/uiModule_runCommand.h>
class displayWidget :public QWidget
{
Q_OBJECT
@@ -29,7 +30,8 @@ public:
dayNightShiftHistogramWidget* _dayNightShiftHistogramWidget;
userSwitch* _userSwitch;
softwareDataDisplay* _softwareDataDisplay;
//uiModuleLocationMap* _uiModuleLocationMap = new uiModuleLocationMap();
ConnectionWidget* _ConnectionWidget = new ConnectionWidget(this);
runCommandWidget* _runCommandWidget;
LogWindow* log = new LogWindow();
displayWidget(appConfig* config) :m_config(config)
{
@@ -172,12 +174,13 @@ public:
lineWidgetJustForShow->setFixedWidth(5);
titleLayout->addWidget(lineWidgetJustForShow);
QFont font3("微软雅黑", 10, QFont::Bold);
#pragma region 日志分析按钮
{
QVBoxLayout* btnLayout = new QVBoxLayout();
QPushButton* btn = new QPushButton(this);
btn->setIcon(QIcon(":/TongYongUiIcon/TongYongUiIcon/4.LogAnalyze.png"));
btn->setFixedSize(QSize(50, 50));
btn->setIconSize(QSize(25, 25)); // 设置图标大小,保持等比例(根据你图标原始比例设置合适尺寸)
btn->setIconSize(QSize(25, 25));
btn->setStyleSheet(R"(
QPushButton {
background-color: transparent;
@@ -198,12 +201,14 @@ public:
emit changeStackWidget(2);
});
}
#pragma endregion
#pragma region 打开配置文件按钮
{
QVBoxLayout* btnLayout = new QVBoxLayout();
QPushButton* btn = new QPushButton(this);
btn->setIcon(QIcon(":/TongYongUiIcon/TongYongUiIcon/9.paramSetting.png"));
btn->setFixedSize(QSize(50, 50));
btn->setIconSize(QSize(25, 25)); // 设置图标大小,保持等比例(根据你图标原始比例设置合适尺寸)
btn->setIconSize(QSize(25, 25));
btn->setStyleSheet(R"(
QPushButton {
background-color: transparent;
@@ -224,11 +229,13 @@ public:
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(config->settingJsonPath)));
});
}
#pragma endregion
#pragma region 结果图查看按钮
{
QVBoxLayout* btnLayout = new QVBoxLayout();
QPushButton* btn = new QPushButton(this);
btn->setIcon(QIcon(":/TongYongUiIcon/TongYongUiIcon/23.1.imageView.png"));
btn->setIconSize(QSize(50, 50)); // 设置图标大小,保持等比例(根据你图标原始比例设置合适尺寸)
btn->setIconSize(QSize(50, 50));
btn->setStyleSheet(R"(
QPushButton {
background-color: transparent;
@@ -249,23 +256,74 @@ public:
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(config->imgSavePath)));
});
}
#pragma endregion
#pragma region 修改检测参数按钮
{
QVBoxLayout* btnLayout = new QVBoxLayout();
QPushButton* btn = new QPushButton(this);
btn->setIcon(QIcon(":/TongYongUiIcon/TongYongUiIcon/search_1.png"));
btn->setFixedSize(QSize(75, 50));
btn->setIconSize(QSize(25, 25));
btn->setStyleSheet(R"(
QPushButton {
background-color: transparent;
border: none;
}
QPushButton:hover {
background-color: black;
border-radius: 5px;
}
)");
QLabel* text = new QLabel("修改检测参数");
text->setFont(font3);
text->setPalette(palette);
btnLayout->addWidget(btn);
btnLayout->addWidget(text);
titleLayout->addLayout(btnLayout);
connect(btn, &QPushButton::clicked, [=]() {
JsonParamTableEditor* dlg = new JsonParamTableEditor(this);
dlg->setJsonObject(m_config->settingJson["backend"]["missionSettings"]),
dlg->setAttribute(Qt::WA_DeleteOnClose);
connect(dlg, &JsonParamTableEditor::jsonAccepted, [this](const nlohmann::json& result) {
m_config->settingJson["backend"]["missionSettings"] = result;
});
dlg->show(); });
}
#pragma endregion
#pragma region 故障排查按钮
{
QVBoxLayout* btnLayout = new QVBoxLayout();
QPushButton* btn = new QPushButton(this);
btn->setIcon(QIcon(":/TongYongUiIcon/TongYongUiIcon/18.help.png"));
btn->setFixedSize(QSize(50, 50));
btn->setIconSize(QSize(25, 25));
btn->setStyleSheet(R"(
QPushButton {
background-color: transparent;
border: none;
}
QPushButton:hover {
background-color: black;
border-radius: 5px;
}
)");
QLabel* text = new QLabel("故障排查");
text->setFont(font3);
text->setPalette(palette);
btnLayout->addWidget(btn);
btnLayout->addWidget(text);
titleLayout->addLayout(btnLayout);
_runCommandWidget = new runCommandWidget();
connect(btn, &QPushButton::clicked, [=]() {
_runCommandWidget->show(); });
}
#pragma endregion
QWidget* spacerWidget = new QWidget;
spacerWidget->setMaximumWidth(1920);
titleLayout->addWidget(spacerWidget, 1);
#endif
fancyButtonText* btn = new fancyButtonText(200, 50, u8"修改检测参数", "");
connect(btn, &QPushButton::clicked, [=]() {
JsonParamTableEditor* dlg = new JsonParamTableEditor(this);
dlg->setJsonObject(m_config->settingJson["backend"]["missionSettings"]),
dlg->setAttribute(Qt::WA_DeleteOnClose);
connect(dlg, &JsonParamTableEditor::jsonAccepted, [this](const nlohmann::json& result) {
m_config->settingJson["backend"]["missionSettings"] = result;
});
dlg->show(); });
titleLayout->addWidget(btn);
titleLayout->addWidget(_ConnectionWidget);
vLayout->addWidget(titleWidget);
vLayout->addWidget(&_ImageWidgetManager);
@@ -1,243 +0,0 @@
#include <front/pages/sqlControlWidget.h>
#include <qlabel.h>
#include <qcombobox.h>
#include <qlineedit.h>
#include <qpushbutton.h>
#include <qstandarditemmodel.h>
#include <qlayout.h>
#include <qtablewidget.h>
#include <appCore.hpp>
sqliteReader::sqliteReader()
{
readIniFile(".//config//sqliteReader.ini");
//_sqlManager = &_core._appConfig._sqlManager;
//std::vector<std::string> res=_sqlManager->getTableList();
//widgetInit(res);
}
sqliteReader::~sqliteReader()
{
//_sqlManager.uninitlize();
}
void sqliteReader::widgetInit(std::vector<std::string>tables)
{
//1
layout1 = new QVBoxLayout();
this->setLayout(layout1);
//1-1
QWidget* vLayout2Widget = new QWidget();
QHBoxLayout * vLayoutt2 = new QHBoxLayout();
vLayout2Widget->setLayout(vLayoutt2);
layout1->addWidget(vLayout2Widget);
//1-1-1
QLabel* vLayout2Label = new QLabel(u8"请选择日期");
vLayoutt2->addWidget(vLayout2Label);
QComboBox * Layou2MBox = new QComboBox();
for (auto &data : tables)
{
Layou2MBox->addItem(QString::fromStdString(data));
}
vLayoutt2->addWidget(Layou2MBox);
connect(Layou2MBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [=]() {switchWidget(Layou2MBox->currentText().toStdString()); });
QLabel* vLayout2Label2 = new QLabel(u8"根据SN查询");
vLayoutt2->addWidget(vLayout2Label2);
QLineEdit *Layout2LEdit = new QLineEdit();
vLayoutt2->addWidget(Layout2LEdit);
QPushButton* layout2QPBtn = new QPushButton(u8"查询");
vLayoutt2->addWidget(layout2QPBtn);
QPushButton* dumpCsvBtn = new QPushButton(u8"导出为csv");
vLayoutt2->addWidget(dumpCsvBtn);
connect(layout2QPBtn,& QPushButton::clicked, this, [=]() {searchSN(Layou2MBox->currentText().toStdString(), Layout2LEdit->text().toStdString()); });
connect(dumpCsvBtn, &QPushButton::clicked, this, [=]() {_dumpToExcel.mainWidget->show(); });
//1-2
tableWidget = new QTableWidget();
layout1->addWidget(tableWidget);
switchWidget(Layou2MBox->currentText().toStdString());
}
void sqliteReader::switchWidget(std::string tableName)
{
#if 0
sqlTableDatas res = _sqlManager->selectAllData(tableName);
tableWidget->clear();
delete tableWidget;
tableWidget = new QTableWidget();
tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
layout1->addWidget(tableWidget);
if (res.rowDatas.size() > 0)
{
int colsNum = res.rowDatas[0].size() + 1 - avoidMap.size();
tableWidget->setColumnCount(colsNum);
//tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("SN"));
//for (int i = 0; i < res.at(0).dataVec.size(); i++)
//创建列名
{
int index = 0;
std::unordered_map<QString, QString>::iterator it;
std::unordered_map<QString, QString>::iterator it2;
for (auto&data : res.rowDatas[0])
{
it = avoidMap.find(QString::fromStdString(data.key));
if (it == avoidMap.end())
{
QString Name = QString::fromStdString(data.key);
it2 = cuttomName.find(Name);
if (it2 != cuttomName.end())
Name = it2->second;
tableWidget->setHorizontalHeaderItem(index, new QTableWidgetItem(Name));
index++;
}
}
}
//tableWidget->setColumnCount(res.size());
for (int i = 0; i < res.rowDatas.size(); i++)
{
//for (auto& data : res.rowDatas[0])
{
int row = tableWidget->rowCount();
tableWidget->insertRow(row);
//tableWidget->setItem(row, 0, new QTableWidgetItem(QString::fromStdString(data.key)));
{
int index = 0;
std::unordered_map<QString, QString>::iterator it;
for (auto& data : res.rowDatas[i])
{
it = avoidMap.find(QString::fromStdString(data.key));
if (it == avoidMap.end())
{
tableWidget->setItem(row, index, new QTableWidgetItem(QString::fromStdString(data.value)));
index++;
}
}
}
}
}
}
#endif
//tableWidget->horizontalHeader
}
void sqliteReader::searchSN(std::string tableName, std::string SN)
{
#if 0
sqlTableDatas res = _sqlManager->selectRowData(SN);
tableWidget->clear();
delete tableWidget;
tableWidget = new QTableWidget();
layout1->addWidget(tableWidget);
if (res.rowDatas.size()>0)//非空
{
tableWidget->setColumnCount(res.rowDatas[0].size() - avoidMap.size());
//tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("SN"));
{
int index = 0;
std::unordered_map<QString, QString>::iterator it;
std::unordered_map<QString, QString>::iterator it2;
for (auto&data : res.rowDatas[0])
{
it = avoidMap.find(QString::fromStdString(data.key));
if (it == avoidMap.end())
{
QString Name = QString::fromStdString(data.key);
it2 = cuttomName.find(Name);
if (it2 != cuttomName.end())
Name = it2->second;
tableWidget->setHorizontalHeaderItem(index, new QTableWidgetItem(Name));
index++;
}
}
}
//tableWidget->setColumnCount(res.dataVec.size());
int row = tableWidget->rowCount();
tableWidget->insertRow(row);
{
int index = 0;
std::unordered_map<QString, QString>::iterator it;
for (auto&data : res.rowDatas[0])
{
it = avoidMap.find(QString::fromStdString(data.key));
if (it == avoidMap.end())
{
tableWidget->setItem(row, index, new QTableWidgetItem(QString::fromStdString(data.value)));
index++;
}
}
}
}
else
{
if(res.rowDatas.size()!=0)
{
tableWidget->setColumnCount(res.rowDatas[0].size() + 1);
tableWidget->setHorizontalHeaderItem(0, new QTableWidgetItem("SN"));
tableWidget->setColumnCount(1);
}
int row = tableWidget->rowCount();
tableWidget->insertRow(row);
tableWidget->setItem(row, 0, new QTableWidgetItem(u8"找不到该数据!"));
}
#endif
//tableWidget->horizontalHeader
}
bool sqliteReader::readIniFile(const QString &filePath) {
//std::unordered_map<QString, QString> avoiData;
//std::unordered_map<QString, QString> cutomName;
QFile file(filePath);
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
QString currentSection;
while (!in.atEnd()) {
QString line = in.readLine().trimmed();
if (line.startsWith('[') && line.endsWith(']')) {
// This line is a section header
currentSection = line.mid(1, line.length() - 2);
}
else if (!line.isEmpty() && !line.startsWith(';') && !currentSection.isEmpty()) {
// This line is a key-value pair within a section
int separatorIndex = line.indexOf('=');
if (separatorIndex != -1) {
if (!currentSection.compare("avoid"))
{
QString key = line.left(separatorIndex).trimmed();
QString value = line.mid(separatorIndex + 1).trimmed();
if (!value.compare("true"))
avoidMap.insert({ key, value });
}
else if (!currentSection.compare("customName"))
{
QString key = line.left(separatorIndex).trimmed();
QString value = line.mid(separatorIndex + 1).trimmed().toUtf8();
cuttomName.insert({ key, value });
}
}
}
}
file.close();
}
else
{
file.close();
return false;
}
return true;
}
+135 -16
View File
@@ -1,28 +1,140 @@
#include <QWidget>
#include <qlayout.h>
#include <qtablewidget.h>
#include <QSqlDatabase>
#include <QSqlQueryModel>
#include <qlabel.h>
#include <qstackedwidget.h>
#include <uiModule/components/fancyButton.h>
#include <uiModule/uiModule_dumpToExcel.h>
#include <QFileDialog>
#include <QMessageBox>
class sqliteReader : public QWidget
{
Q_OBJECT
public:
sqliteReader();
~sqliteReader();
QVBoxLayout* layout1;
QTableWidget* tableWidget;
//sqlManager* _sqlManager;
dumpToExcel _dumpToExcel;
std::unordered_map<QString, QString>avoidMap;//不显示该数据
std::unordered_map<QString, QString>cuttomName;//自定义列名
void widgetInit(std::vector<std::string>tables);
void switchWidget(std::string tableNam);
void searchSN(std::string tableNam, std::string SN);
bool readIniFile(const QString& filePath);
sqliteReader() {
QFont font("微软雅黑", 12, QFont::Bold);
QPalette palette;
palette.setColor(QPalette::WindowText, Qt::white);
//1-1
QHBoxLayout* vLayout = new QHBoxLayout();
layout->addLayout(vLayout);
//1-1-1
QLabel* showLabel = new QLabel(u8"班次");
showLabel->setFont(font);
showLabel->setPalette(palette);
vLayout->addWidget(showLabel);
tableSelectComboBox->setFixedWidth(150);
vLayout->addWidget(tableSelectComboBox);
connect(tableSelectComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [=]() {switchWidget(tableSelectComboBox->currentText()); });
refreshBtn->setFont(font);
refreshBtn->setPalette(palette);
vLayout->addWidget(refreshBtn);
connect(refreshBtn, &QPushButton::clicked,
this, [=]() {refreshTable(); });
QLabel* showLabel2 = new QLabel(u8"SN查询");
showLabel2->setFont(font);
showLabel2->setPalette(palette);
vLayout->addWidget(showLabel2);
QLineEdit* snInputLineEdit = new QLineEdit();
vLayout->addWidget(snInputLineEdit);
vLayout->addWidget(searchSnBtn);
connect(searchSnBtn, &QPushButton::clicked, this, [=]() {searchSN(tableSelectComboBox->currentText(), snInputLineEdit->text()); });
vLayout->addWidget(dumpToCsvBtn);
connect(dumpToCsvBtn, &QPushButton::clicked, this, [=]() {dumpToCsv(tableSelectComboBox->currentText()); });
//1-2
layout->addWidget(tableWidget);
}
appConfig* _config;
//QTableView* view = new QTableView;
void refreshTable() {
tableSelectComboBox->clear();
auto tables = _config->g_db->getTables();
for (int i = tables.size() - 1; i > 0 ; i--){
if (!tables[i].contains("set"))
tableSelectComboBox->addItem(tables[i]);
}
}
void switchWidget(QString tableName) {
QSqlQueryModel* model = new QSqlQueryModel;
model->setQuery("SELECT * from \"" + tableName + "\"");
if (model->lastError().isValid()) {
qDebug() << "查询失败:" << model->lastError().text();
return;
}
tableWidget->setModel(model);
}
void searchSN(QString tableName, QString SN) {
// Construct SQL query to search for SN in the specified table
QString queryStr = QString("SELECT * FROM \"%1\" WHERE 条码 = '%2'")
.arg(tableName)
.arg(SN);
QSqlQueryModel* model = new QSqlQueryModel;
model->setQuery(queryStr);
if (model->lastError().isValid()) {
qDebug() << "SN查询失败:" << model->lastError().text();
// Optionally clear the table or show an error
tableWidget->setModel(nullptr);
return;
}
tableWidget->setModel(model);
}
void dumpToCsv(QString tableName) {
// 打开文件管理器,默认文件名为表名.csv
QString filePath = QFileDialog::getSaveFileName(
this,
u8"导出为CSV",
QDir::homePath() + "/" + tableName + ".csv",
u8"CSV文件 (*.csv)"
);
if (filePath.isEmpty()) {
return; // 用户取消
}
// 导出数据
bool success = false;
if (_config && _config->g_db) {
std::mutex mutex;
success = _config->g_db->exportTableToCSV(tableName, filePath, mutex);
}
// 提示导出结果
if (success) {
QMessageBox::information(this, u8"导出成功", u8"数据已成功导出到:\n" + filePath);
} else {
QMessageBox::warning(this, u8"导出失败", u8"导出CSV文件失败,请检查路径或数据库状态。");
}
}
private:
QComboBox* tableSelectComboBox = new QComboBox();
QVBoxLayout* layout = new QVBoxLayout(this);
QTableView* tableWidget = new QTableView();
fancyButtonText* refreshBtn = new fancyButtonText(80, 25, u8"刷新", "");
fancyButtonText* searchSnBtn = new fancyButtonText(80, 25, u8"查询", "");
fancyButtonText* dumpToCsvBtn = new fancyButtonText(80, 25, u8"导出", "");
protected:
void showEvent(QShowEvent* event) override {
QWidget::showEvent(event);
refreshTable();
}
};
class sqlControlWidget :public QWidget
{
@@ -36,8 +148,15 @@ public:
QTableWidget* sqlWidget = new QTableWidget();
QLabel* disconnnectedLabel = new QLabel("服务已离线");
sqlControlWidget()
{
sqlControlWidget(appConfig* _configIN){
_sqliteReader._config = _configIN;
this->setObjectName("sqlControlWidget");
this->setStyleSheet(R"(
QWidget#sqlControlWidget {
background: rgb(50, 55, 60);
border-radius: 10px; /* 圆角半径 */
}
)");
QPalette palette;
palette.setColor(QPalette::WindowText, Qt::white);
QFont font("微软雅黑", 24, QFont::Bold);
@@ -70,8 +189,8 @@ public:
//btnLayout->addWidget(sqlWidget);
Layout->addLayout(btnLayout);
Layout->addWidget(&_sqliteReader);
}
};
#pragma once
@@ -398,10 +398,8 @@ protected:
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
int radius = 10; // 圆角半径
int radius = 10;
QRect r = rect();
// 填充圆角背景
painter.setBrush(QColor(50, 55, 60));
painter.setPen(Qt::NoPen);
painter.drawRoundedRect(r, radius, radius);
+2 -2
View File
@@ -245,7 +245,7 @@ void MainWindow::leftBarInit(){
registerPageBar(":/icon/icon/config.png", u8"日志", _logWidget);
//手动检测
_manualDetWidget = new manualDetWidget();
//_manualDetWidget = new manualDetWidget(m_config);
//registerPageBar(":/icon/icon/cycleButton.png", u8"手动检测", _manualDetWidget);
//历史图片
@@ -253,7 +253,7 @@ void MainWindow::leftBarInit(){
//registerPageBar(":/icon/icon/history.png", u8"历史图片", _historyWidget);
//SQL
_sqlControlWidget = new sqlControlWidget();
_sqlControlWidget = new sqlControlWidget(config);
registerPageBar(":/icon/icon/sql.png", u8"数据库", _sqlControlWidget);
//PLUGIN
+1 -1
View File
@@ -290,7 +290,7 @@ signals:
protected:
void mouseDoubleClickEvent(QMouseEvent* event) override
{
if (event->pos().y() > 35)
if (event->pos().y() < 35)
return
toggleMaximize(reverse);
QMainWindow::mouseDoubleClickEvent(event);
@@ -119,7 +119,6 @@ public:
// 设置按钮显示√
SaveBtn.setText("√");
SaveBtn.toGreen();
// 创建一个定时器
QTimer::singleShot(1000, [=]() mutable {
// 一秒后还原文本
SaveBtn.toDefault();
@@ -104,5 +104,70 @@ private:
QMutex mutex;
int okCnt = 0, ngCnt = 0;
};
class stateLabel :public QLabel {
public:
QPixmap okImg, errorImg;
QTimer* timer = nullptr;
QPixmap transparent;
bool blink = false;
stateLabel(QString okImgPath,QString errorImgPath, QWidget* parent = nullptr) {
okImg = QPixmap(okImgPath).scaled(25, 25, Qt::KeepAspectRatio, Qt::SmoothTransformation);
errorImg = QPixmap(errorImgPath).scaled(25, 25, Qt::KeepAspectRatio, Qt::SmoothTransformation);
transparent = QPixmap(okImg);
transparent.fill(Qt::transparent); // 透明图片
this->setPixmap(okImg);
this->setAlignment(Qt::AlignCenter);
}
void setOK() {
blink = false;
this->setPixmap(okImg);
if (timer != nullptr) {
delete timer;
timer = nullptr;
}
}
void setError() {
if (!timer) {
//this->setPixmap(errorImg);
timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, [this]() mutable {
blink = !blink;
if (blink == false) {
this->setPixmap(transparent);
}
else {
this->setPixmap(errorImg);
}
});
}
if (!timer->isActive())
timer->start(600);
}
};
class ConnectionWidget : public QWidget {
public:
QVBoxLayout* layout = new QVBoxLayout(this);
stateLabel* lanConnectonLabel = new stateLabel(":/icon/icon/lan_connection_ok.png", ":/icon/icon/lan_connection_error.png",this);
stateLabel* camConnectonLabel = new stateLabel(":/icon/icon/cam_connection_ok.png", ":/icon/icon/cam_connection_error.png", this);
QPixmap lanConnectionOk, lanConnectionError, camConnectionOK, camConnectionError;
QTimer* timer1 = nullptr,*timer2 = nullptr;
QPixmap transparent1, transparent2;
ConnectionWidget(QWidget* parent = nullptr) :
QWidget(parent){
layout->addWidget(lanConnectonLabel);
layout->addWidget(camConnectonLabel);
}
void setPlcConnected() {
lanConnectonLabel->setOK();
}
void setPlcDisconnected() {
lanConnectonLabel->setError();
}
void setCamConnected() {
camConnectonLabel->setOK();
}
void setCamDisconnected() {
camConnectonLabel->setError();
}
};
#pragma once
+10 -11
View File
@@ -250,7 +250,7 @@ class ImageWidget : public QWidget {
Q_OBJECT
public:
QComboBox switchBox;
QMutex switchBoxMutex;
QMutex switchViewerMutex;
ImageWidget(QWidget* parent = nullptr) : QWidget(parent) {
QVBoxLayout* layout = new QVBoxLayout(this);
setObjectName("ImageWidget");
@@ -267,23 +267,22 @@ public:
QFont font("微软雅黑", 8 , QFont::Bold);
QWidget* hWidget = new QWidget(this);
QHBoxLayout* hLayout = new QHBoxLayout(hWidget);
hWidget->setFixedHeight(15);
#if switchToTongYongUi == 0
hWidget->setFixedHeight(16);
auto spaceItem = new QSpacerItem(100, 1);
hLayout->addSpacerItem(spaceItem);
#endif
label = new QLabel(u8"相机标签");
label->setAlignment(Qt::AlignLeft);
label->setFont(font);
label->setPalette(palette);
label->setFixedHeight(10 * 2);
label->setFixedHeight(21);
switchBox.setFont(font);
switchBox.setPalette(palette);
switchBox.setFixedHeight(21);
switchBox.setFixedWidth(100);
#if switchToTongYongUi == 1
switchBox.hide();
#endif
connect(&switchBox, &QComboBox::currentTextChanged, [=](QString type)
{
switchViewType(type);
@@ -333,7 +332,7 @@ public slots:
//combobox切换槽
void switchViewType(QString name)
{
QMutexLocker locker(&switchBoxMutex);
QMutexLocker locker(&switchViewerMutex);
auto& it = map.find(name);
if (it == map.end())
{
@@ -363,7 +362,7 @@ public slots:
return;
}
it.value() = std::make_shared<QPixmap>(resImgInput);
QMutexLocker locker(&switchBoxMutex);
QMutexLocker locker(&switchViewerMutex);
if (type == switchBox.currentText())
showImgOnGraphicsView(resImgInput);
}
@@ -0,0 +1,52 @@
#include <qdialog.h>
#include <global.h>
#include <nlohmannJson.hpp>
#include <qlayout.h>
class runCommandWidget : public QDialog {
Q_OBJECT
public:
explicit runCommandWidget(QWidget* parent = nullptr)
: QDialog(parent) {
this->setWindowTitle("执行命令");
this->resize(400, 800);
//setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint); // 去掉边框 //现在、、
//setAttribute(Qt::WA_TranslucentBackground); // 背景透明
this->setObjectName("JsonParamTableEditor");
this->setStyleSheet(QString("QDialog#JsonParamTableEditor {background-color: rgb(%1);border: 2px solid #000000;border-radius: 6px;}").arg(sColor_Blue));
btnWidgets = new QListWidget(this);
btnWidgets->setStyleSheet("background: transparent;");
QVBoxLayout* layout = new QVBoxLayout(this);
layout->addWidget(btnWidgets);
this->setFixedSize(sizeX, sizeY);
}
signals:
void excuteCommandPreset(QString uuid);
public slots:
void addBtn(const QString& btnName, const QString& tip, const QString& uuid) {
QListWidgetItem* item = new QListWidgetItem(btnWidgets);
item->setSizeHint(QSize(sizeX - 30, 30));
btnWidgets->addItem(item);
fancyButtonText* funcBtn = new fancyButtonText(sizeX - 30, 30, btnName, tip);
btnWidgets->setItemWidget(item, funcBtn);
connect(funcBtn, &fancyButtonText::clicked, this, [this, uuid]() {
QMessageBox::StandardButton reply;
reply = QMessageBox::question(
this, // 父窗口
"提示", // 标题
"确定要执行此操作吗?", // 内容
QMessageBox::Yes | QMessageBox::No // 按钮
);
if (reply == QMessageBox::Yes) {
emit excuteCommandPreset(uuid);
}
});
}
private:
int sizeX = 300, sizeY = 500;
QListWidget* btnWidgets;
};
#pragma once
+2 -1
View File
@@ -2,6 +2,7 @@
#include <string>
#include <global.h>
#include <generalJsonParsing.hpp>
#include <sql/qSqlBase.h>
class appConfig
{
public:
@@ -19,7 +20,7 @@ public:
nlohmann::ordered_json settingJson;
std::string softwareTile;//软件标题
std::string imgSavePath;//原图存储路径
SQLiteDB* g_db = nullptr;
//triggerStruct _triggerStruct;
//std::vector< cameraStruct> _cameraStructs;
//sqlConfigStruct _sqlConfigStruct;
+2 -3
View File
@@ -5,7 +5,6 @@
#include <appConfig/appConfig.h>
//QT
#include <qtimer.h>
#include <sql/qSqlBase.h>
//
#include "interface.h"
#include <qtBridge.h>
@@ -57,7 +56,7 @@ public:
logService _logService;
appConfig _appConfig;
backEnd backend;
SQLiteDB* g_db = nullptr;
appCore(){
};
@@ -67,7 +66,7 @@ public slots:
}
void recvInitFinished() {
g_db = backend.backend->getDatabase();
_appConfig.g_db = backend.backend->getDatabase();
}
};
+5 -1
View File
@@ -20,6 +20,8 @@ logService::logService()
_logToQtWidget->sendStdLogSignal(outPutMsg);//Qt日志界面
_logToQtWidget->sendMainWindowStdLogSignal(outPutMsg);//Qt主界面
_logService->qtLogger->LogDebug("[STD]" + output);//spdLog
});
_stdConsoleRedirector->registerCallback([&](const std::string& output) {
_stdConsoleRedirector->writeToConsole(output);
});
// QT日志到 spdLog Qt日志界面
@@ -27,7 +29,9 @@ logService::logService()
_logService->qtLogger->LogDebug("[QT]" + output.toStdString());
_logToQtWidget->sendQtLogSignal(output);//Qt日志界面
});
_qtRediretor->registerCallback([&](const QString& output) {
_stdConsoleRedirector->writeToConsole(output.toStdString()); // 逐个字符写入缓冲区
});
}
logService::~logService()
+4
View File
@@ -38,6 +38,10 @@ public:
logToQtWidget* _logToQtWidget;
//SpdLogger stdLogger;
SpdLogger* qtLogger;
void disableConsole() {
_stdConsoleRedirector->eraseSecondCallback();
_qtRediretor->eraseSecondCallback();
}
logService();
~logService();
};
+7 -1
View File
@@ -1,6 +1,6 @@
#include <qapplication.h>
#include <qfileinfo.h>
#include <mutex>
class qtRediretor
{
public:
@@ -11,10 +11,16 @@ public:
}
void sendMsg(QString& msg)
{
std::lock_guard<std::mutex> lock(consoleLock);
for (auto& callback : callbacks)
callback(msg);
}
void eraseSecondCallback() {
std::lock_guard<std::mutex> lock(consoleLock);
callbacks.erase(callbacks.begin() + 1, callbacks.end());
}
private:
std::mutex consoleLock;
std::vector<CallbackType> callbacks;
};
+4
View File
@@ -33,6 +33,10 @@ public:
void registerCallback(CallbackType callback) {
callbacks.push_back(callback);
}
void eraseSecondCallback() {
std::lock_guard<std::mutex> lock(consoleLock);
callbacks.erase(callbacks.begin() + 1, callbacks.end());
}
void writeToConsole(const std::string& str) {
std::lock_guard<std::mutex> lock(consoleLock);
originalBuffer->sputn(str.c_str(), str.size());
+16
View File
@@ -128,6 +128,14 @@ void connectSignalAndSlot(appCore* _core, MainWindow* _MainWindow, qtFuncBridge*
QObject::connect(bridge, &qtFuncBridge::histogramWidgetAddData,
_MainWindow, [=](std::vector<std::string>defects)
{_MainWindow->_displayWidget->_dayNightShiftHistogramWidget->addDefect(defects); });
QObject::connect(bridge, &qtFuncBridge::setPlcConnectionError,
_MainWindow, [=]() {_MainWindow->_displayWidget->_ConnectionWidget->setPlcDisconnected(); });
QObject::connect(bridge, &qtFuncBridge::setPlcConnectionOk,
_MainWindow, [=]() {_MainWindow->_displayWidget->_ConnectionWidget->setPlcConnected(); });
QObject::connect(bridge, &qtFuncBridge::setCamConnectionError,
_MainWindow, [=]() {_MainWindow->_displayWidget->_ConnectionWidget->setCamDisconnected(); });
QObject::connect(bridge, &qtFuncBridge::setCamConnectionOk,
_MainWindow, [=]() {_MainWindow->_displayWidget->_ConnectionWidget->setCamConnected(); });
//登录界面
QObject::connect(bridge, &qtFuncBridge::initResult,
_MainWindow, &MainWindow::recvInitFinished);
@@ -140,6 +148,13 @@ void connectSignalAndSlot(appCore* _core, MainWindow* _MainWindow, qtFuncBridge*
//波形图
QObject::connect(bridge, &qtFuncBridge::summaryData_addData,
_MainWindow, &MainWindow::slot_summaryData_addData);
//排障
QObject::connect(bridge, &qtFuncBridge::runCommand_addBtn,
_MainWindow->_displayWidget->_runCommandWidget, &runCommandWidget::addBtn);
QObject::connect(_MainWindow->_displayWidget->_runCommandWidget,
&runCommandWidget::excuteCommandPreset,
[=](QString uuid) {_core->backend.backend->excuteCliCommandPreset(uuid); });
}
int main(int argc, char* argv[])
@@ -194,6 +209,7 @@ int main(int argc, char* argv[])
#if HIDE_CONSOLE
if (hWnd) {
ShowWindow(hWnd, SW_HIDE);
_core._logService.disableConsole();
}// 隐藏控制台窗口
#endif
return a.exec();
+3 -2
View File
@@ -40,8 +40,8 @@ FILE(GLOB UI_FILES "./*.ui")
#find_package(Qt5 COMPONENTS Core REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Gui Network Sql REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Gui Network Sql REQUIRED)
add_library(${CURRENT_FOLDER} SHARED
${HEAD_FILES}
@@ -64,6 +64,7 @@ target_link_libraries(${CURRENT_FOLDER} PRIVATE
Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Network
Qt${QT_VERSION_MAJOR}::Sql
)
+5 -1
View File
@@ -2,4 +2,8 @@ json1.0.4
心跳改为数组,循环发送
去除Triggers{readNum,sleepTime,writeType}
json1.0.5
批量读取改为数组 readAllCmd
批量读取改为数组 readAllCmd
json1.0.6
加入心跳间隔heartBeatIntervalMS
加入图像压缩阈值uiShowImgCompressThreshold
加入睡眠时间sleepIntervalMS