#include "stdafx.h" #include "Common.h" #include "AlarmManager.h" #include "Log.h" #include #include #include #include #include #include #include #include // 常量 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; } } // 初始化报警表 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 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; } // 创建单元表,设备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, severity_level INTEGER NOT NULL DEFAULT 0, device_id TEXT NOT NULL , unit_id TEXT NOT NULL, description TEXT NOT NULL, start_time DATETIME NOT NULL, end_time DATETIME, FOREIGN KEY (device_id) REFERENCES devices(device_id), FOREIGN KEY (unit_id) REFERENCES units(unit_id) ) )"; if (!m_pDB->executeQuery(createAlarmsTableQuery)) { return false; } // 设备列表 (ID -> 名称) std::vector> devices = { {0, "Software"}, {EQ_ID_LOADPORT1, EQ_NAME_LOADPORT1}, {EQ_ID_LOADPORT2, EQ_NAME_LOADPORT2}, {EQ_ID_LOADPORT3, EQ_NAME_LOADPORT3}, {EQ_ID_LOADPORT4, EQ_NAME_LOADPORT4}, {EQ_ID_ARM_TRAY1, EQ_NAME_ARM_TRAY1}, {EQ_ID_ARM_TRAY2, EQ_NAME_ARM_TRAY2}, {EQ_ID_ALIGNER, EQ_NAME_ALIGNER}, {EQ_ID_FLIPER, EQ_NAME_FLIPER}, {EQ_ID_VACUUMBAKE, EQ_NAME_VACUUMBAKE}, {EQ_ID_Bonder1, EQ_NAME_BONDER1}, {EQ_ID_Bonder2, EQ_NAME_BONDER2}, {EQ_ID_BAKE_COOLING, EQ_NAME_BAKE_COOLING}, {EQ_ID_MEASUREMENT, EQ_NAME_MEASUREMENT}, {EQ_ID_EFEM, EQ_NAME_EFEM}, {EQ_ID_ARM, EQ_NAME_ARM}, {EQ_ID_OPERATOR_REMOVE, EQ_NAME_OPERATOR_REMOVE} }; // 插入 devices 和对应的默认 unit for (const auto& dev : devices) { int nDeviceId = dev.first; const std::string& strDeviceName = dev.second; // 插入设备 std::ostringstream ossDev; ossDev << "INSERT OR IGNORE INTO devices (device_id, device_name) VALUES(" << nDeviceId << ", '" << strDeviceName << "')"; if (!m_pDB->executeQuery(ossDev.str())) { return false; } // 插入默认单元 (unit_id = 0, unit_name = device_name) std::ostringstream ossUnit; ossUnit << "INSERT OR IGNORE INTO units (device_id, unit_id, unit_name) VALUES(" << nDeviceId << ", 0, '" << strDeviceName << "')"; if (!m_pDB->executeQuery(ossUnit.str())) { return false; } } return true; } // 销毁报警表 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); } // 插入模拟数据 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 = 0; j <= 3; ++j) { int unitId = j; std::string deviceId = std::to_string(i); std::string unitName = "Unit" + std::to_string(j); std::stringstream query; query << "INSERT INTO units (device_id, unit_id, unit_name) VALUES ('" << deviceId << "', '" // 插入设备ID,确保是字符串 << unitId << "', '" // 插入单元ID,确保是字符串 << 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, 3); std::uniform_int_distribution<> errorCodeDis(1, 100); std::uniform_int_distribution<> severityDis(0, 3); std::vector 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); // 随机错误码 int severityLevel = severityDis(gen); // 随机生成报警等级 std::string description = descriptions[errorCodeDis(gen) % descriptions.size()]; // 随机报警描述 std::stringstream query; query << "INSERT INTO alarms (id, severity_level, device_id, unit_id, description, start_time, end_time) " << "VALUES (" << errorCode << ", " << severityLevel << ", " << 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; } } */ } // 添加报警信息 bool AlarmManager::addAlarm(const AlarmData& alarmData, int& alarmEventId) { if (!m_pDB) { return false; } #if 0 // 开始事务 m_pDB->executeQuery("BEGIN TRANSACTION;"); // 构建插入查询 std::ostringstream query; query << "INSERT INTO alarms (id, severity_level, device_id, unit_id, description, start_time, end_time) VALUES (" << alarmData.nId << ", " // 错误码 << alarmData.nSeverityLevel << ", " // 报警等级 << alarmData.nDeviceId << ", " // 设备ID << alarmData.nUnitId << ", '" // 单元ID << alarmData.strDescription << "', '" // 描述 << alarmData.strStartTime << "', '" // 开始时间 << alarmData.strEndTime << "')"; // 结束时间 // 使用锁保护多线程安全 std::lock_guard lock(m_mutex); // 执行插入查询 bool result = m_pDB->executeQuery(query.str()); if (result) { alarmEventId = getLastInsertId(); m_alarmCache[alarmEventId] = alarmData; } // 提交事务 m_pDB->executeQuery("COMMIT;"); return result; #else for (AlarmDataMap::const_iterator it = m_mapCache.begin(); it != m_mapCache.end(); ++it) { const AlarmData& alarm = it->second; if (alarm.nId == alarmData.nId && alarm.nDeviceId == alarmData.nDeviceId && alarm.nUnitId == alarmData.nUnitId) { alarmEventId = it->first; return false; } } // 构建插入查询并使用 RETURNING 获取插入后的 alarm_event_id std::ostringstream query; query << "INSERT INTO alarms (id, severity_level, device_id, unit_id, description, start_time, end_time) " << "VALUES (" << alarmData.nId << ", " << alarmData.nSeverityLevel << ", " << alarmData.nDeviceId << ", " << alarmData.nUnitId << ", '" << alarmData.strDescription << "', '" << alarmData.strStartTime << "', '" << alarmData.strEndTime << "') RETURNING alarm_event_id;"; // 使用锁保护多线程安全 std::lock_guard lock(m_mutex); // 执行查询并获取结果 auto results = m_pDB->fetchResults(query.str()); if (!results.empty() && !results[0].empty()) { try { // 提取并转换 alarm_event_id alarmEventId = std::stoi(results[0][0]); // 将插入的报警数据添加到缓存 m_mapCache[alarmEventId] = alarmData; return true; } catch (const std::exception& e) { std::cerr << "Error parsing alarm_event_id: " << e.what() << std::endl; return false; } } return false; #endif } // 查询所有报警数据 std::vector AlarmManager::getAllAlarms() { if (!m_pDB) { return {}; } // 查询所有报警数据(包括设备名称和单元名称) const std::string query = R"( SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id )"; auto results = m_pDB->fetchResults(query); // 遍历查询结果,填充 AlarmData 结构体 std::vector alarms; for (const auto& row : results) { AlarmData alarmData; alarmData.nId = std::stoi(row[0]); // 错误码 alarmData.nSeverityLevel = std::stoi(row[1]); // 报警等级 alarmData.nDeviceId = std::stoi(row[2]); // 设备ID alarmData.nUnitId = std::stoi(row[3]); // 单元ID alarmData.strDeviceName = row[4]; // 设备名称 alarmData.strUnitName = row[5]; // 单元名称 alarmData.strDescription = row[6]; // 描述 alarmData.strStartTime = row[7]; // 开始时间 alarmData.strEndTime = row[8]; // 结束时间 alarms.push_back(alarmData); } return alarms; } // 根据报警ID查询报警 std::vector AlarmManager::getAlarmsById(const std::string& id) { if (!m_pDB) { return {}; } std::ostringstream query; query << R"( SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id WHERE a.id = ')" << id << "'"; auto results = m_pDB->fetchResults(query.str()); // 遍历查询结果,填充 AlarmData 结构体 std::vector alarms; for (const auto& row : results) { AlarmData alarmData; alarmData.nId = std::stoi(row[0]); // 错误码 alarmData.nSeverityLevel = std::stoi(row[1]); // 报警等级 alarmData.nDeviceId = std::stoi(row[2]); // 设备ID alarmData.nUnitId = std::stoi(row[3]); // 单元ID alarmData.strDeviceName = row[4]; // 设备名称 alarmData.strUnitName = row[5]; // 单元名称 alarmData.strDescription = row[6]; // 描述 alarmData.strStartTime = row[7]; // 开始时间 alarmData.strEndTime = row[8]; // 结束时间 alarms.push_back(alarmData); } return alarms; } // 根据描述查询报警 std::vector AlarmManager::getAlarmsByDescription(const std::string& description) { if (!m_pDB) { return {}; } std::ostringstream query; query << R"( SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id WHERE a.description LIKE '%)" << description << R"(%')"; auto results = m_pDB->fetchResults(query.str()); // 遍历查询结果,填充 AlarmData 结构体 std::vector alarms; for (const auto& row : results) { AlarmData alarmData; alarmData.nId = std::stoi(row[0]); // 错误码 alarmData.nSeverityLevel = std::stoi(row[1]); // 报警等级 alarmData.nDeviceId = std::stoi(row[2]); // 设备ID alarmData.nUnitId = std::stoi(row[3]); // 单元ID alarmData.strDeviceName = row[4]; // 设备名称 alarmData.strUnitName = row[5]; // 单元名称 alarmData.strDescription = row[6]; // 描述 alarmData.strStartTime = row[7]; // 开始时间 alarmData.strEndTime = row[8]; // 结束时间 alarms.push_back(alarmData); } return alarms; } // 根据时间范围查询报警 std::vector AlarmManager::getAlarmsByTimeRange(const std::string& startTime, const std::string& endTime) { if (!m_pDB) { return {}; } std::ostringstream query; query << R"( SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id WHERE 1=1)"; if (!startTime.empty()) { query << " AND a.start_time >= '" << startTime << "'"; } if (!endTime.empty()) { query << " AND a.end_time <= '" << endTime << "'"; } auto results = m_pDB->fetchResults(query.str()); // 遍历查询结果,填充 AlarmData 结构体 std::vector alarms; for (const auto& row : results) { AlarmData alarmData; alarmData.nId = std::stoi(row[0]); // 错误码 alarmData.nSeverityLevel = std::stoi(row[1]); // 报警等级 alarmData.nDeviceId = std::stoi(row[2]); // 设备ID alarmData.nUnitId = std::stoi(row[3]); // 单元ID alarmData.strDeviceName = row[4]; // 设备名称 alarmData.strUnitName = row[5]; // 单元名称 alarmData.strDescription = row[6]; // 描述 alarmData.strStartTime = row[7]; // 开始时间 alarmData.strEndTime = row[8]; // 结束时间 alarms.push_back(alarmData); } return alarms; } // 根据ID、开始时间和结束时间查询报警 std::vector AlarmManager::getAlarmsByIdAndTimeRange(const std::string& id, const std::string& startTime, const std::string& endTime) { if (!m_pDB) { return {}; } std::ostringstream query; query << R"( SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id WHERE a.id = ')" << id << "'"; if (!startTime.empty()) { query << " AND a.start_time >= '" << startTime << "'"; } if (!endTime.empty()) { query << " AND a.end_time <= '" << endTime << "'"; } auto results = m_pDB->fetchResults(query.str()); // 遍历查询结果,填充 AlarmData 结构体 std::vector alarms; for (const auto& row : results) { AlarmData alarmData; alarmData.nId = std::stoi(row[0]); // 错误码 alarmData.nSeverityLevel = std::stoi(row[1]); // 报警等级 alarmData.nDeviceId = std::stoi(row[2]); // 设备ID alarmData.nUnitId = std::stoi(row[3]); // 单元ID alarmData.strDeviceName = row[4]; // 设备名称 alarmData.strUnitName = row[5]; // 单元名称 alarmData.strDescription = row[6]; // 描述 alarmData.strStartTime = row[7]; // 开始时间 alarmData.strEndTime = row[8]; // 结束时间 alarms.push_back(alarmData); } return alarms; } // 分页查询报警数据 std::vector AlarmManager::getAlarms(int startPosition, int count) { if (!m_pDB) { return {}; } std::ostringstream query; query << R"( SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id LIMIT )" << count << " OFFSET " << startPosition; auto results = m_pDB->fetchResults(query.str()); // 遍历查询结果,填充 AlarmData 结构体 std::vector alarms; for (const auto& row : results) { AlarmData alarmData; alarmData.nId = std::stoi(row[0]); // 错误码 alarmData.nSeverityLevel = std::stoi(row[1]); // 报警等级 alarmData.nDeviceId = std::stoi(row[2]); // 设备ID alarmData.nUnitId = std::stoi(row[3]); // 单元ID alarmData.strDeviceName = row[4]; // 设备名称 alarmData.strUnitName = row[5]; // 单元名称 alarmData.strDescription = row[6]; // 描述 alarmData.strStartTime = row[7]; // 开始时间 alarmData.strEndTime = row[8]; // 结束时间 alarms.push_back(alarmData); } return alarms; } // 获取当前未结束的报警(end_time 为空),并可按 start_time 最近 N 小时过滤 std::vector AlarmManager::getActiveAlarms(int recentHours /*=12*/) { if (!m_pDB) { return {}; } // 计算时间阈值:当前时间减 recentHours std::string cutoffTime; if (recentHours > 0) { using namespace std::chrono; auto cutoff = system_clock::now() - hours(recentHours); std::time_t t = system_clock::to_time_t(cutoff); std::tm tm {}; localtime_s(&tm, &t); char buf[32] = { 0 }; std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm); cutoffTime = buf; } std::ostringstream query; query << R"( SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id WHERE a.end_time IS NULL OR a.end_time = '' )"; if (!cutoffTime.empty()) { query << " AND a.start_time >= '" << cutoffTime << "'"; } query << " ORDER BY a.start_time DESC"; auto lastErrStr = []() -> std::string { DWORD gle = GetLastError(); if (gle == 0) return {}; LPSTR buf = nullptr; size_t len = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, gle, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, nullptr); std::string s = (buf && len > 0) ? std::string(buf, len) : ""; if (buf) LocalFree(buf); return s; }; std::vector> results; try { results = m_pDB->fetchResults(query.str()); } catch (const std::exception& ex) { DWORD gle = GetLastError(); auto errStr = lastErrStr(); LOGE("getActiveAlarms failed: %s, GLE=%lu (%s)", ex.what(), gle, errStr.c_str()); return {}; } std::vector alarms; auto toInt = [](const std::string& s) -> int { try { return std::stoi(s); } catch (...) { return 0; } }; for (const auto& row : results) { if (row.size() < 9) continue; AlarmData alarmData; alarmData.nId = toInt(row[0]); alarmData.nSeverityLevel = toInt(row[1]); alarmData.nDeviceId = toInt(row[2]); alarmData.nUnitId = toInt(row[3]); alarmData.strDeviceName = row[4]; alarmData.strUnitName = row[5]; alarmData.strDescription = row[6]; alarmData.strStartTime = row[7]; alarmData.strEndTime = row[8]; alarms.push_back(alarmData); } return alarms; } // 筛选报警数据 std::vector AlarmManager::getFilteredAlarms(const std::string& keyword, const std::string& startTime, const std::string& endTime, int pageNumber, int pageSize) { if (!m_pDB) { return {}; } std::ostringstream query; query << R"( SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id WHERE 1=1)"; // 统一关键字模糊查询 if (!keyword.empty()) { query << " AND (" << "a.id LIKE '%" << keyword << "%' OR " << "a.severity_level LIKE '%" << keyword << "%' OR " << "d.device_name LIKE '%" << keyword << "%' OR " << "u.unit_name LIKE '%" << keyword << "%' OR " << "a.description LIKE '%" << keyword << "%')"; } // 时间条件 if (!startTime.empty()) { query << " AND a.start_time >= '" << startTime << "'"; } if (!endTime.empty()) { query << " AND a.end_time <= '" << endTime << "'"; } // 分页设置 int nOffset = (pageNumber - 1) * pageSize; query << " ORDER BY a.start_time DESC LIMIT " << pageSize << " OFFSET " << nOffset; // 查询 auto results = m_pDB->fetchResults(query.str()); // 遍历查询结果,填充 AlarmData 结构体 std::vector alarms; for (const auto& row : results) { AlarmData alarmData; alarmData.nId = std::stoi(row[0]); // 错误码 alarmData.nSeverityLevel = std::stoi(row[1]); // 报警等级 (字符串) alarmData.nDeviceId = std::stoi(row[2]); // 设备ID alarmData.nUnitId = std::stoi(row[3]); // 单元ID alarmData.strDeviceName = row[4]; // 设备名称 alarmData.strUnitName = row[5]; // 单元名称 alarmData.strDescription = row[6]; // 描述 alarmData.strStartTime = row[7]; // 开始时间 alarmData.strEndTime = row[8]; // 结束时间 alarms.push_back(alarmData); } return alarms; } // 获取符合条件的报警总数 int AlarmManager::getTotalAlarmCount(const std::string& keyword, const std::string& startTime, const std::string& endTime) { if (!m_pDB) { return 0; } std::ostringstream query; query << R"( SELECT COUNT(*) FROM alarms a JOIN devices d ON a.device_id = d.device_id JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id WHERE 1=1)"; // 统一关键字模糊查询 if (!keyword.empty()) { query << " AND (" << "a.id LIKE '%" << keyword << "%' OR " << "a.severity_level LIKE '%" << keyword << "%' OR " << "d.device_name LIKE '%" << keyword << "%' OR " << "u.unit_name LIKE '%" << keyword << "%' OR " << "a.description LIKE '%" << keyword << "%')"; } // 时间条件 if (!startTime.empty()) { query << " AND a.start_time >= '" << startTime << "'"; } if (!endTime.empty()) { query << " AND a.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& severityLevel, const std::string& deviceId, const std::string& unitId, const std::string& description, const std::string& startTime, const std::string& newEndTime) { if (!m_pDB) { return false; } // 更新报警结束时间 std::ostringstream updateQuery; updateQuery << "UPDATE alarms SET end_time = '" << newEndTime << "'" << " WHERE id = '" << id << "'" << " AND severity_level = '" << severityLevel << "'" << " AND device_id = '" << deviceId << "'" << " AND unit_id = '" << unitId << "'" << " AND description = '" << description << "'" << " AND start_time = '" << startTime << "'"; return m_pDB->executeQuery(updateQuery.str()); } // 清理旧报警数据 void AlarmManager::cleanOldAlarms(int daysToKeep, const std::string& deviceId, const std::string& unitId) { if (!m_pDB) { return; } std::ostringstream query; query << "DELETE FROM alarms WHERE end_time < datetime('now', '-" << daysToKeep << " days')"; if (!deviceId.empty()) { query << " AND device_id = '" << deviceId << "'"; } if (!unitId.empty()) { query << " AND unit_id = '" << unitId << "'"; } m_pDB->executeQuery(query.str()); } // 通过设备ID获取设备名称 std::string AlarmManager::getDeviceNameById(int deviceId) { if (!m_pDB) { return ""; } std::ostringstream query; query << "SELECT device_name FROM devices WHERE device_id = " << deviceId; auto result = m_pDB->fetchResults(query.str()); if (result.empty()) { return ""; } return result[0][0]; // 返回查询到的设备名称 } // 通过设备ID和单元ID获取单元名称 std::string AlarmManager::getUnitNameById(int deviceId, int unitId) { if (!m_pDB) { return ""; } std::ostringstream query; query << "SELECT unit_name FROM units WHERE device_id = " << deviceId << " AND unit_id = " << unitId; auto result = m_pDB->fetchResults(query.str()); if (result.empty()) { return ""; } return result[0][0]; // 返回查询到的单元名称 } // 获取最近插入的 alarm_event_id int AlarmManager::getLastInsertId() { std::string query = "SELECT last_insert_rowid();"; auto results = m_pDB->fetchResults(query); if (results.empty() || results[0].empty()) { return -1; } // 从查询结果中获取最后插入的 ID int lastInsertId = std::stoi(results[0][0]); return lastInsertId; } // 通过 alarm_event_id 解除报警(更新结束时间) bool AlarmManager::clearAlarmByEventId(int alarmEventId, const std::string& endTime) { if (!m_pDB) { return false; } bool result = true; auto it = m_mapCache.find(alarmEventId); if (it != m_mapCache.end()) { std::lock_guard lock(m_mutex); std::ostringstream query; query << "UPDATE alarms SET end_time = '" << endTime << "' WHERE alarm_event_id = " << alarmEventId << ";"; bool result = m_pDB->executeQuery(query.str()); if (result) { m_mapCache.erase(it); } } return result; } // 通过多个属性查找并解除报警(更新结束时间) bool AlarmManager::clearAlarmByAttributes(int nId, int nDeviceId, int nUnitId, const std::string& endTime) { if (!m_pDB) { return false; } std::lock_guard lock(m_mutex); // 先在缓存中查找匹配的 alarm_event_id int alarmEventId = -1; for (AlarmDataMap::const_iterator it = m_mapCache.begin(); it != m_mapCache.end(); ++it) { const AlarmData& alarm = it->second; if (alarm.nId == nId && alarm.nDeviceId == nDeviceId && alarm.nUnitId == nUnitId) { alarmEventId = it->first; break; } } // 缓存未命中时,从数据库查找仍未结束的记录(取最新一条) if (alarmEventId == -1) { std::ostringstream querySel; querySel << "SELECT alarm_event_id FROM alarms WHERE " << "id = " << nId << " AND device_id = " << nDeviceId << " AND unit_id = " << nUnitId << " AND (end_time IS NULL OR end_time = '') " << "ORDER BY start_time DESC LIMIT 1;"; auto results = m_pDB->fetchResults(querySel.str()); if (!results.empty() && !results[0].empty()) { try { alarmEventId = std::stoi(results[0][0]); } catch (...) { alarmEventId = -1; } } } // 如果没找到匹配的记录,则直接返回 false if (alarmEventId == -1) { return false; } // 构建 SQL 语句,使用找到的 alarm_event_id 来更新结束时间 std::ostringstream query; query << "UPDATE alarms SET end_time = '" << endTime << "' WHERE alarm_event_id = " << alarmEventId << ";"; bool result = m_pDB->executeQuery(query.str()); if (result) { m_mapCache.erase(alarmEventId); } return result; } // 读取报警文件 bool AlarmManager::readAlarmFile(const std::string& filename) { std::ifstream file(filename, std::ios::binary); if (!file.is_open()) { std::cerr << "Error opening file!" << std::endl; return false; } auto getline_cross = [](std::ifstream& f, std::string& out) -> bool { out.clear(); char ch; while (f.get(ch)) { if (ch == '\r') { // 处理 \r\n 或 单独 \r if (f.peek() == '\n') f.get(); break; } else if (ch == '\n') { break; } out.push_back(ch); } return !out.empty() || !f.eof(); }; std::string line; bool first_line = true; while (getline_cross(file, line)) { if (first_line) { first_line = false; continue; } std::stringstream ss(line); std::string cell; AlarmInfo alarm; try { if (!std::getline(ss, cell, ',')) throw std::runtime_error("Missing field: No"); if (!std::getline(ss, alarm.strUnitID, ',')) throw std::runtime_error("Missing field: UnitID"); if (!std::getline(ss, alarm.strUnitNo, ',')) throw std::runtime_error("Missing field: UnitNo"); if (!std::getline(ss, cell, ',')) throw std::runtime_error("Missing field: AlarmLevel"); alarm.nAlarmLevel = std::stoi(cell); if (!std::getline(ss, cell, ',')) throw std::runtime_error("Missing field: AlarmCode"); alarm.nAlarmCode = std::stoi(cell); if (!std::getline(ss, cell, ',')) throw std::runtime_error("Missing field: AlarmID"); alarm.nAlarmID = std::stoi(cell); if (!std::getline(ss, alarm.strAlarmText, ',')) throw std::runtime_error("Missing field: AlarmText"); if (!std::getline(ss, alarm.strDescription, ',')) throw std::runtime_error("Missing field: Description"); if (m_mapAlarm.find(alarm.nAlarmID) == m_mapAlarm.end()) { m_mapAlarm[alarm.nAlarmID] = alarm; } else { std::cerr << "Duplicate AlarmID: " << alarm.nAlarmID << std::endl; } } catch (const std::exception& e) { std::cerr << "Error parsing line: " << line << " - " << e.what() << std::endl; continue; } } 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 AlarmManager::getAlarmsInfoByIDs(const std::vector& alarmIDs) const { std::vector 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; }