| | |
| | | #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)"; |
| | |
| | | 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); |
| | | } |
| | | |
| | | // 销毁报警表 |
| | |
| | | } |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 添加报警 |
| | |
| | | } |
| | | 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; |
| | | } |