From 4d1e6979820d9aaf27890a833ae0fcb6959e8637 Mon Sep 17 00:00:00 2001
From: LAPTOP-SNT8I5JK\Boounion <Chenluhua@qq.com>
Date: 星期四, 27 二月 2025 15:33:03 +0800
Subject: [PATCH] 1.完善警告信息,打通CC-Link获取警告信息到通过SECS上报警告信息的路径。

---
 SourceCode/Bond/Servo/AlarmManager.cpp |  214 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 206 insertions(+), 8 deletions(-)

diff --git a/SourceCode/Bond/Servo/AlarmManager.cpp b/SourceCode/Bond/Servo/AlarmManager.cpp
index 7864235..0200658 100644
--- a/SourceCode/Bond/Servo/AlarmManager.cpp
+++ b/SourceCode/Bond/Servo/AlarmManager.cpp
@@ -1,9 +1,12 @@
 #include "stdafx.h"
 #include "AlarmManager.h"
 #include <sstream>
+#include <fstream>
 #include <iostream>
 #include <stdexcept>
 #include <ctime>
+#include <iomanip>
+#include <random>
 
 // 常量
 const std::string DATABASE_FILE = R"(AlarmManager.db)";
@@ -51,17 +54,46 @@
         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
+    // 创建设备表
+    const std::string createDevicesTableQuery = R"(
+        CREATE TABLE IF NOT EXISTS devices (
+            device_id TEXT PRIMARY KEY NOT NULL,
+            device_name TEXT NOT NULL
         )
     )";
+    if (!m_pDB->executeQuery(createDevicesTableQuery)) {
+        return false;
+    }
 
-    return m_pDB->executeQuery(createTableQuery);
+    // 创建单元表,设备ID和单元ID组合作为主键
+    const std::string createUnitsTableQuery = R"(
+        CREATE TABLE IF NOT EXISTS units (
+            device_id TEXT NOT NULL,
+            unit_id TEXT NOT NULL,
+            unit_name TEXT NOT NULL,
+            PRIMARY KEY (device_id, unit_id),
+            FOREIGN KEY (device_id) REFERENCES devices(device_id)
+        )
+    )";
+    if (!m_pDB->executeQuery(createUnitsTableQuery)) {
+        return false;
+    }
+
+    // 创建报警表,报警记录的alarm_event_id是主键
+    const std::string createAlarmsTableQuery = R"(
+        CREATE TABLE IF NOT EXISTS alarms (
+            alarm_event_id INTEGER PRIMARY KEY AUTOINCREMENT,
+            id TEXT NOT NULL,
+            device_id TEXT NOT NULL,
+            unit_id TEXT NOT NULL,
+            description TEXT NOT NULL,
+            start_time DATETIME NOT NULL,
+            end_time DATETIME NOT NULL,
+            FOREIGN KEY (device_id) REFERENCES devices(device_id),
+            FOREIGN KEY (unit_id) REFERENCES units(unit_id)
+        )
+    )";
+    return m_pDB->executeQuery(createAlarmsTableQuery);
 }
 
 // 销毁报警表
@@ -78,6 +110,68 @@
 	}
 	const std::string dropTableQuery = "DROP TABLE IF EXISTS alarms";
 	return m_pDB->executeQuery(dropTableQuery);
+}
+
+// 插入模拟数据
+void AlarmManager::insertMockData() {
+    // 插入设备数据
+    for (int i = 1; i <= 3; ++i) {
+        std::string deviceName = "Device" + std::to_string(i);
+        std::stringstream query;
+        query << "INSERT INTO devices (device_id, device_name) VALUES (" << i << ", '" << deviceName << "');";
+        if (!m_pDB->executeQuery(query.str())) {
+            std::cerr << "Failed to insert device: " << i << std::endl;
+        }
+    }
+
+    // 插入单元数据
+    for (int i = 1; i <= 3; ++i) {
+        for (int j = 1; j <= 3; ++j) {
+            int unitId = (i - 1) * 3 + j;
+            std::string unitName = "Unit" + std::to_string(j);
+            std::stringstream query;
+            query << "INSERT INTO units (device_id, unit_id, unit_name) VALUES (" << i << "', " << unitId << ", '" << unitName << ");";
+            if (!m_pDB->executeQuery(query.str())) {
+                std::cerr << "Failed to insert unit: " << unitId << std::endl;
+            }
+        }
+    }
+
+    // 初始化随机数生成器
+    std::random_device rd;
+    std::mt19937 gen(rd());
+    std::uniform_int_distribution<> deviceDis(1, 3);
+    std::uniform_int_distribution<> unitDis(1, 9);
+    std::uniform_int_distribution<> errorCodeDis(1, 3);
+    std::vector<std::string> descriptions = { "Overheat", "Sensor failure", "Power outage" };
+
+    // 时间相关
+    auto now = std::chrono::system_clock::now();
+    auto start_time = std::chrono::system_clock::to_time_t(now);
+    auto end_time = std::chrono::system_clock::to_time_t(now + std::chrono::minutes(10));
+
+    std::tm start_tm = {};
+    std::tm end_tm = {};
+    localtime_s(&start_tm, &start_time);
+    localtime_s(&end_tm, &end_time);
+
+    // 插入模拟数据
+    for (int i = 0; i < 10; ++i) {
+        int deviceId = deviceDis(gen);      // 随机设备ID
+        int unitId = unitDis(gen);          // 随机单元ID
+        int errorCode = errorCodeDis(gen);  // 随机错误码
+        std::string description = descriptions[errorCodeDis(gen) % descriptions.size()];  // 随机报警描述
+
+        std::stringstream query;
+        query << "INSERT INTO alarms (id, device_id, unit_id, description, start_time, end_time) "
+            << "VALUES (" << errorCode << ", " << deviceId << ", " << unitId << ", '" << description << "', "
+            << "'" << std::put_time(&start_tm, "%Y-%m-%d %H:%M:%S") << "', "
+            << "'" << std::put_time(&end_tm, "%Y-%m-%d %H:%M:%S") << "');";
+
+        if (!m_pDB->executeQuery(query.str())) {
+            std::cerr << "Failed to insert alarm data." << std::endl;
+        }
+    }
 }
 
 // 添加报警
@@ -287,3 +381,107 @@
     }
     m_pDB->executeQuery(query.str());
 }
+
+// 读取报警文件
+bool AlarmManager::readAlarmFile(const std::string& filename) {
+    std::ifstream file(filename);
+    std::string line;
+    bool first_line = true;
+
+    if (!file.is_open()) {
+        std::cerr << "Error opening file!" << std::endl;
+        return false;
+    }
+
+    while (std::getline(file, line)) {
+        if (first_line) {
+            first_line = false;
+            continue;
+        }
+
+        std::stringstream ss(line);
+        std::string cell;
+        AlarmInfo alarm;
+
+        std::getline(ss, cell, ',');
+        std::getline(ss, alarm.strUnitID, ',');
+        std::getline(ss, alarm.strUnitNo, ',');
+        std::getline(ss, cell, ',');
+        alarm.nAlarmLevel = 0;// std::stoi(cell);
+        std::getline(ss, cell, ',');
+        alarm.nAlarmCode = std::stoi(cell);
+        std::getline(ss, cell, ',');
+        alarm.nAlarmID = std::stoi(cell);
+        std::getline(ss, alarm.strAlarmText, ',');
+        std::getline(ss, alarm.strDescription, ',');
+
+        if (m_mapAlarm.find(alarm.nAlarmID) == m_mapAlarm.end()) {
+            m_mapAlarm[alarm.nAlarmID] = alarm;
+        }
+        else {
+            std::cerr << "Duplicate AlarmID: " << alarm.nAlarmID << std::endl;
+        }
+    }
+
+    file.close();
+    return true;
+}
+
+// 将报警数据保存到文件
+bool AlarmManager::saveAlarmFile(const std::string& filename) {
+    std::ofstream file(filename);
+
+    if (!file.is_open()) {
+        std::cerr << "打开文件写入失败!" << std::endl;
+        return false;
+    }
+
+    // 写入标题行
+    file << "No,UNIT ID,UNIT NO,Alarm Level,Alarm Code,AlarmID,Alarm Text,Description\n";
+
+    // 写入报警数据
+    int nIndex = 1;
+    for (const auto& pair : m_mapAlarm) {
+        const AlarmInfo& alarm = pair.second;
+        file << nIndex++ << ","
+            << alarm.strUnitID << ","
+            << alarm.strUnitNo << ","
+            << alarm.nAlarmLevel << ","
+            << alarm.nAlarmCode << ","
+            << alarm.nAlarmID << ","
+            << alarm.strAlarmText << ","
+            << alarm.strDescription << "\n";
+    }
+
+    file.close();
+    return true;
+}
+
+// 通过 AlarmID 查询对应的报警信息
+const AlarmInfo* AlarmManager::getAlarmInfoByID(int nAlarmID) const {
+    auto it = m_mapAlarm.find(nAlarmID);
+    if (it != m_mapAlarm.end()) {
+        return &(it->second);
+    }
+    else {
+        std::cerr << "未找到 AlarmID: " << nAlarmID << std::endl;
+        return nullptr;
+    }
+}
+
+// 通过多个 AlarmID 查询对应的报警信息
+std::vector<AlarmInfo> AlarmManager::getAlarmsInfoByIDs(const std::vector<int>& alarmIDs) const {
+    std::vector<AlarmInfo> alarms;
+
+    for (int alarmID : alarmIDs) {
+        auto it = m_mapAlarm.find(alarmID);
+        if (it != m_mapAlarm.end()) {
+            alarms.push_back(it->second);
+        }
+        else {
+            std::cerr << "未找到 AlarmID: " << alarmID << std::endl;
+        }
+    }
+
+    return alarms;
+}
\ No newline at end of file

--
Gitblit v1.9.3