From 700ca509ba853d1615ea3e5c470d2532006f0e1e Mon Sep 17 00:00:00 2001
From: darker <mr.darker@163.com>
Date: 星期五, 17 一月 2025 15:21:34 +0800
Subject: [PATCH] 1. 添加报警管理器,新增设备名称
---
SourceCode/Bond/Servo/Servo.vcxproj | 4
SourceCode/Bond/Servo/AlarmManager.cpp | 289 ++++++++++++++++++++++++++++++++
SourceCode/Bond/Servo/Servo.vcxproj.filters | 6
SourceCode/Bond/Servo/AlarmManager.h | 163 ++++++++++++++++++
SourceCode/Bond/Servo/Servo.cpp | 19 ++
SourceCode/Bond/Servo/stdafx.h | 22 ++
SourceCode/Bond/Servo/ServoDlg.cpp | 1
7 files changed, 504 insertions(+), 0 deletions(-)
diff --git a/SourceCode/Bond/Servo/AlarmManager.cpp b/SourceCode/Bond/Servo/AlarmManager.cpp
new file mode 100644
index 0000000..7864235
--- /dev/null
+++ b/SourceCode/Bond/Servo/AlarmManager.cpp
@@ -0,0 +1,289 @@
+#include "stdafx.h"
+#include "AlarmManager.h"
+#include <sstream>
+#include <iostream>
+#include <stdexcept>
+#include <ctime>
+
+// 常量
+const std::string DATABASE_FILE = R"(AlarmManager.db)";
+
+// 静态成员初始化
+std::mutex AlarmManager::m_mutex;
+
+// 获取单例实例
+AlarmManager& AlarmManager::getInstance() {
+ static AlarmManager instance;
+ return instance;
+}
+
+// 构造函数
+AlarmManager::AlarmManager() {
+ m_pDB = new BL::SQLiteDatabase();
+}
+
+// 析构函数
+AlarmManager::~AlarmManager() {
+ if (m_pDB != nullptr) {
+ delete m_pDB;
+ m_pDB = nullptr;
+ }
+}
+
+// 设置数据库连接
+void AlarmManager::setDatabase(BL::Database* db) {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ m_pDB = db;
+}
+
+// 初始化报警表
+bool AlarmManager::initAlarmTable() {
+ char path[MAX_PATH];
+ GetModuleFileName(NULL, path, MAX_PATH);
+ std::string exePath(path);
+ std::string dbFileDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB";
+ if (!CreateDirectory(dbFileDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != GetLastError()) {
+ throw std::runtime_error("Failed to create database directory.");
+ }
+
+ std::string dbFilePath = dbFileDir + "\\" + DATABASE_FILE;
+ if (!m_pDB->connect(dbFilePath, true)) {
+ throw std::runtime_error("Failed to connect to database.");
+ }
+
+ const std::string createTableQuery = R"(
+ CREATE TABLE IF NOT EXISTS alarms (
+ id TEXT NOT NULL,
+ device_name TEXT NOT NULL,
+ description TEXT NOT NULL,
+ start_time DATETIME NOT NULL,
+ end_time DATETIME NOT NULL
+ )
+ )";
+
+ return m_pDB->executeQuery(createTableQuery);
+}
+
+// 销毁报警表
+void AlarmManager::termAlarmTable() {
+ if (m_pDB != nullptr) {
+ m_pDB->disconnect();
+ }
+}
+
+// 销毁报警表
+bool AlarmManager::destroyAlarmTable() {
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+ const std::string dropTableQuery = "DROP TABLE IF EXISTS alarms";
+ return m_pDB->executeQuery(dropTableQuery);
+}
+
+// 添加报警
+bool AlarmManager::addAlarm(const std::string& id, const std::string& deviceName, const std::string& description, const std::string& startTime, const std::string& endTime) {
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "INSERT INTO alarms (id, device_name, description, start_time, end_time) VALUES ("
+ << "'" << id << "', "
+ << "'" << deviceName << "', "
+ << "'" << description << "', "
+ << "'" << startTime << "', "
+ << "'" << endTime << "')";
+
+ std::lock_guard<std::mutex> lock(m_mutex);
+ return m_pDB->executeQuery(query.str());
+}
+
+// 查询所有报警数据
+std::vector<std::vector<std::string>> AlarmManager::getAllAlarms() {
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ const std::string query = "SELECT id, device_name, description, start_time, end_time FROM alarms";
+ return m_pDB->fetchResults(query);
+}
+
+// 根据报警ID查询报警
+std::vector<std::vector<std::string>> AlarmManager::getAlarmsById(const std::string& id) {
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE id = '" << id << "'";
+ return m_pDB->fetchResults(query.str());
+}
+
+// 根据描述查询报警
+std::vector<std::vector<std::string>> AlarmManager::getAlarmsByDescription(const std::string& description) {
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE description LIKE '%" << description << "%'";
+ return m_pDB->fetchResults(query.str());
+}
+
+// 根据时间范围查询报警
+std::vector<std::vector<std::string>> AlarmManager::getAlarmsByTimeRange(
+ const std::string& startTime, const std::string& endTime) {
+
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE 1=1";
+
+ if (!startTime.empty()) {
+ query << " AND start_time >= '" << startTime << "'";
+ }
+ if (!endTime.empty()) {
+ query << " AND end_time <= '" << endTime << "'";
+ }
+
+ return m_pDB->fetchResults(query.str());
+}
+
+// 根据ID、开始时间和结束时间查询报警
+std::vector<std::vector<std::string>> AlarmManager::getAlarmsByIdAndTimeRange(
+ const std::string& id, const std::string& startTime, const std::string& endTime) {
+
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE id = '" << id << "'";
+
+ if (!startTime.empty()) {
+ query << " AND start_time >= '" << startTime << "'";
+ }
+ if (!endTime.empty()) {
+ query << " AND end_time <= '" << endTime << "'";
+ }
+
+ return m_pDB->fetchResults(query.str());
+}
+
+// 分页查询报警数据
+std::vector<std::vector<std::string>> AlarmManager::getAlarms(int startPosition, int count) {
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "SELECT id, device_name, description, start_time, end_time FROM alarms LIMIT " << count << " OFFSET " << startPosition;
+ return m_pDB->fetchResults(query.str());
+}
+
+// 筛选报警数据
+std::vector<std::vector<std::string>> AlarmManager::getFilteredAlarms(
+ const std::string& id,
+ const std::string& deviceName,
+ const std::string& description,
+ const std::string& startTime,
+ const std::string& endTime,
+ int pageNumber,
+ int pageSize) {
+
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "SELECT id, device_name, description, start_time, end_time FROM alarms WHERE 1=1";
+
+ if (!id.empty()) {
+ query << " AND id = '" << id << "'";
+ }
+ if (!deviceName.empty()) {
+ query << " AND device_name LIKE '%" << deviceName << "%'";
+ }
+ if (!description.empty()) {
+ query << " AND description LIKE '%" << description << "%'";
+ }
+ if (!startTime.empty()) {
+ query << " AND start_time >= '" << startTime << "'";
+ }
+ if (!endTime.empty()) {
+ query << " AND end_time <= '" << endTime << "'";
+ }
+
+ int offset = (pageNumber - 1) * pageSize;
+ query << " ORDER BY start_time DESC LIMIT " << pageSize << " OFFSET " << offset;
+
+ return m_pDB->fetchResults(query.str());
+}
+
+// 获取符合条件的报警总数
+int AlarmManager::getTotalAlarmCount(
+ const std::string& id,
+ const std::string& deviceName,
+ const std::string& description,
+ const std::string& startTime,
+ const std::string& endTime) {
+
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "SELECT COUNT(*) FROM alarms WHERE 1=1";
+
+ if (!id.empty()) {
+ query << " AND id = '" << id << "'";
+ }
+ if (!deviceName.empty()) {
+ query << " AND device_name LIKE '%" << deviceName << "%'";
+ }
+ if (!description.empty()) {
+ query << " AND description LIKE '%" << description << "%'";
+ }
+ if (!startTime.empty()) {
+ query << " AND start_time >= '" << startTime << "'";
+ }
+ if (!endTime.empty()) {
+ query << " AND end_time <= '" << endTime << "'";
+ }
+
+ auto results = m_pDB->fetchResults(query.str());
+ return (!results.empty() && !results[0].empty()) ? std::stoi(results[0][0]) : 0;
+}
+
+// 更新报警的结束时间
+bool AlarmManager::updateAlarmEndTime(const std::string& id, const std::string& deviceName, const std::string& description, const std::string& startTime, const std::string& newEndTime) {
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "UPDATE alarms SET end_time = '" << newEndTime << "'"
+ << " WHERE id = '" << id << "'"
+ << " AND device_name = '" << deviceName << "'"
+ << " AND description = '" << description << "'"
+ << " AND start_time = '" << startTime << "'";
+
+ return m_pDB->executeQuery(query.str());
+}
+
+// 清理旧报警数据
+void AlarmManager::cleanOldAlarms(int daysToKeep, const std::string& deviceName) {
+ if (!m_pDB) {
+ throw std::runtime_error("Database connection is not set.");
+ }
+
+ std::ostringstream query;
+ query << "DELETE FROM alarms WHERE end_time < datetime('now', '-" << daysToKeep << " days')";
+
+ if (!deviceName.empty()) {
+ query << " AND device_name = '" << deviceName << "'";
+ }
+ m_pDB->executeQuery(query.str());
+}
diff --git a/SourceCode/Bond/Servo/AlarmManager.h b/SourceCode/Bond/Servo/AlarmManager.h
new file mode 100644
index 0000000..28bea98
--- /dev/null
+++ b/SourceCode/Bond/Servo/AlarmManager.h
@@ -0,0 +1,163 @@
+#ifndef ALARM_MANAGER_H
+#define ALARM_MANAGER_H
+
+#include <string>
+#include <vector>
+#include <mutex>
+#include "Database.h"
+
+class AlarmManager {
+public:
+ /**
+ * 获取单例实例
+ * @return AlarmManager实例的引用
+ */
+ static AlarmManager& getInstance();
+
+ /**
+ * 设置数据库连接
+ * @param db 数据库连接的指针
+ */
+ void setDatabase(BL::Database* db);
+
+ /**
+ * 初始化报警表
+ * @return 成功返回true,失败返回false
+ */
+ bool initAlarmTable();
+
+ /**
+ * 销毁报警表
+ */
+ void termAlarmTable();
+
+ /**
+ * 销毁报警表
+ * @return 成功返回true,失败返回false
+ */
+ bool destroyAlarmTable();
+
+ /**
+ * 添加报警
+ * @param id 报警ID
+ * @param deviceName 设备名称
+ * @param description 报警描述
+ * @param startTime 报警开始时间
+ * @param endTime 报警结束时间
+ * @return 成功返回true,失败返回false
+ */
+ bool addAlarm(const std::string& id, const std::string& deviceName, const std::string& description, const std::string& startTime, const std::string& endTime);
+
+ /**
+ * 查询所有报警数据
+ * @return 包含所有报警数据的二维字符串向量
+ */
+ std::vector<std::vector<std::string>> getAllAlarms();
+
+ /**
+ * 根据报警ID查询报警
+ * @param id 报警ID
+ * @return 包含筛选后报警数据的二维字符串向量
+ */
+ std::vector<std::vector<std::string>> getAlarmsById(const std::string& id);
+
+ /**
+ * 根据描述查询报警
+ * @param description 报警描述的筛选条件
+ * @return 包含筛选后报警数据的二维字符串向量
+ */
+ std::vector<std::vector<std::string>> getAlarmsByDescription(const std::string& description);
+
+ /**
+ * 根据时间范围查询报警
+ * @param startTime 起始时间
+ * @param endTime 结束时间
+ * @return 包含查询结果的二维字符串向量
+ */
+ std::vector<std::vector<std::string>> getAlarmsByTimeRange(
+ const std::string& startTime, const std::string& endTime);
+
+ /**
+ * 根据ID和时间范围查询报警
+ * @param id 报警ID
+ * @param startTime 起始时间
+ * @param endTime 结束时间
+ * @return 包含查询结果的二维字符串向量
+ */
+ std::vector<std::vector<std::string>> getAlarmsByIdAndTimeRange(
+ const std::string& id, const std::string& startTime, const std::string& endTime);
+
+ /**
+ * 获取报警数据
+ * @param startPosition 起始位置
+ * @param count 获取的记录数量
+ * @return 包含报警数据的二维字符串向量
+ */
+ std::vector<std::vector<std::string>> getAlarms(int startPosition, int count);
+
+ /**
+ * 获取筛选后的报警数据
+ * @param id 报警ID的筛选条件
+ * @param deviceName 设备名称的筛选条件
+ * @param description 报警描述的筛选条件
+ * @param startTime 起始时间筛选条件
+ * @param endTime 结束时间筛选条件
+ * @param pageNumber 页码
+ * @param pageSize 每页的记录数
+ * @return 包含筛选后报警数据的二维字符串向量
+ */
+ std::vector<std::vector<std::string>> getFilteredAlarms(
+ const std::string& id,
+ const std::string& deviceName,
+ const std::string& description,
+ const std::string& startTime,
+ const std::string& endTime,
+ int pageNumber,
+ int pageSize);
+
+ /**
+ * 获取符合条件的报警总数
+ * @param id 报警ID的筛选条件
+ * @param deviceName 设备名称的筛选条件
+ * @param description 报警描述的筛选条件
+ * @param startTime 起始时间筛选条件
+ * @param endTime 结束时间筛选条件
+ * @return 符合条件的报警总数
+ */
+ int getTotalAlarmCount(
+ const std::string& id,
+ const std::string& deviceName,
+ const std::string& description,
+ const std::string& startTime,
+ const std::string& endTime);
+
+ /**
+ * 更新报警结束时间
+ * @param id 报警ID
+ * @param description 报警描述
+ * @param startTime 报警开始时间
+ * @param newEndTime 新的报警结束时间
+ * @return 成功返回true,失败返回false
+ */
+ bool updateAlarmEndTime(const std::string& id, const std::string& deviceName, const std::string& description, const std::string& startTime, const std::string& newEndTime);
+
+ /**
+ * 清理旧报警
+ * @param daysToKeep 保留的天数
+ * @param deviceName 设备名称
+ */
+ void cleanOldAlarms(int daysToKeep = 30, const std::string& deviceName = "");
+
+private:
+ AlarmManager();
+ ~AlarmManager();
+
+ // 禁止拷贝和赋值
+ AlarmManager(const AlarmManager&) = delete;
+ AlarmManager& operator=(const AlarmManager&) = delete;
+
+ BL::Database* m_pDB;
+ static std::mutex m_mutex;
+};
+
+#endif // ALARM_MANAGER_H
\ No newline at end of file
diff --git a/SourceCode/Bond/Servo/Servo.cpp b/SourceCode/Bond/Servo/Servo.cpp
index 550391a..495b5e7 100644
--- a/SourceCode/Bond/Servo/Servo.cpp
+++ b/SourceCode/Bond/Servo/Servo.cpp
@@ -6,6 +6,7 @@
#include "Servo.h"
#include "ServoDlg.h"
#include "ServoGraph.h"
+#include "AlarmManager.h"
// 声明全局变量,用于管理 GDI+ 初始化
ULONG_PTR g_diplusToken;
@@ -101,6 +102,21 @@
InitGDIPlus();
+ // 初始化报警管理器
+ try {
+ if (!AlarmManager::getInstance().initAlarmTable()) {
+ AfxMessageBox("初始化报警管理器失败!");
+ return FALSE;
+ }
+ }
+ catch (const std::exception& ex) {
+ CString errorMsg;
+ errorMsg.Format(_T("初始化报警管理器失败:%s"), CString(ex.what()));
+ AfxMessageBox(errorMsg, MB_ICONERROR);
+ return FALSE;
+ }
+
+
CServoDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
@@ -140,6 +156,9 @@
// 清理 GDI+
TermGDIPlus();
+ // 销毁报警表
+ AlarmManager::getInstance().termAlarmTable();
+
return CWinApp::ExitInstance();
}
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj b/SourceCode/Bond/Servo/Servo.vcxproj
index d0153cb..695b5e7 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -115,6 +115,7 @@
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
+ <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -168,6 +169,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
+ <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -190,6 +192,7 @@
<Text Include="ReadMe.txt" />
</ItemGroup>
<ItemGroup>
+ <ClInclude Include="AlarmManager.h" />
<ClInclude Include="BlButton.h" />
<ClInclude Include="Common.h" />
<ClInclude Include="Configuration.h" />
@@ -209,6 +212,7 @@
<ClInclude Include="targetver.h" />
</ItemGroup>
<ItemGroup>
+ <ClCompile Include="AlarmManager.cpp" />
<ClCompile Include="BlButton.cpp" />
<ClCompile Include="Configuration.cpp" />
<ClCompile Include="Context.cpp" />
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index 1f263f5..5bc0cc3 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -69,6 +69,9 @@
<ClInclude Include="SecsTestDlg.h">
<Filter>澶存枃浠�</Filter>
</ClInclude>
+ <ClInclude Include="AlarmManager.h">
+ <Filter>澶存枃浠�</Filter>
+ </ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Servo.cpp">
@@ -113,6 +116,9 @@
<ClCompile Include="SecsTestDlg.cpp">
<Filter>婧愭枃浠�</Filter>
</ClCompile>
+ <ClCompile Include="AlarmManager.cpp">
+ <Filter>婧愭枃浠�</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="Servo.rc">
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index 07cb989..f349071 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -9,6 +9,7 @@
#include "Common.h"
#include "Log.h"
#include "SecsTestDlg.h"
+#include "AlarmManager.h"
#include <chrono>
#include <thread>
#include <cmath>
diff --git a/SourceCode/Bond/Servo/stdafx.h b/SourceCode/Bond/Servo/stdafx.h
index 9b9a811..4768d25 100644
--- a/SourceCode/Bond/Servo/stdafx.h
+++ b/SourceCode/Bond/Servo/stdafx.h
@@ -33,10 +33,32 @@
#include <afxcontrolbars.h> // 功能区和控件条的 MFC 支持
+
// GDI+
#include <gdiplus.h>
using namespace Gdiplus;
+
+// 数据库模块
+#include "..\DatabaseSDK\include\Database.h"
+#include "..\DatabaseSDK\include\MySQLDatabase.h"
+#include "..\DatabaseSDK\include\SQLiteDatabase.h"
+
+#if defined(_WIN64)
+#if defined(_DEBUG)
+#pragma comment(lib, "..\\DatabaseSDK\\lib\\x64\\Debug\\DatabaseEx.lib")
+#else
+#pragma comment(lib, "..\\DatabaseSDK\\lib\\x64\\Release\\DatabaseEx.lib")
+#endif
+#else
+#if defined(_DEBUG)
+#pragma comment(lib, "..\\DatabaseSDK\\lib\\Win32\\Debug\\DatabaseEx.lib")
+#else
+#pragma comment(lib, "..\\DatabaseSDK\\lib\\Win32\\Release\\DatabaseEx.lib")
+#endif
+#endif
+
+
#include "..\RxWindows1.0\include\RxWindowsLib.h"
#include "..\HSMSSDK\Include\HSMSSDK.h"
--
Gitblit v1.9.3