| | |
| | | #include "stdafx.h" |
| | | #include "Common.h" |
| | | #include "AlarmManager.h" |
| | | #include <sstream> |
| | | #include <fstream> |
| | |
| | | delete m_pDB; |
| | | m_pDB = nullptr; |
| | | } |
| | | } |
| | | |
| | | // 设置数据库连接 |
| | | void AlarmManager::setDatabase(BL::Database* db) { |
| | | std::lock_guard<std::mutex> lock(m_mutex); |
| | | m_pDB = db; |
| | | } |
| | | |
| | | // 初始化报警表 |
| | |
| | | FOREIGN KEY (unit_id) REFERENCES units(unit_id) |
| | | ) |
| | | )"; |
| | | return m_pDB->executeQuery(createAlarmsTableQuery); |
| | | if (!m_pDB->executeQuery(createAlarmsTableQuery)) { |
| | | return false; |
| | | } |
| | | |
| | | // 设备列表 (ID -> 名称) |
| | | std::vector<std::pair<int, std::string>> devices = { |
| | | {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; |
| | | } |
| | | |
| | | // 销毁报警表 |
| | |
| | | } |
| | | |
| | | // 筛选报警数据 |
| | | std::vector<AlarmData> AlarmManager::getFilteredAlarms( |
| | | const std::string& id, |
| | | const std::string& severityLevel, |
| | | const std::string& deviceName, |
| | | const std::string& unitName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime, |
| | | int pageNumber, |
| | | int pageSize) { |
| | | |
| | | std::vector<AlarmData> AlarmManager::getFilteredAlarms(const std::string& keyword, const std::string& startTime, const std::string& endTime, int pageNumber, int pageSize) { |
| | | if (!m_pDB) { |
| | | return {}; |
| | | } |
| | |
| | | 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 |
| | | JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id |
| | | WHERE 1=1)"; |
| | | |
| | | // 传入的过滤条件 |
| | | if (!id.empty()) { |
| | | query << " AND a.id = '" << id << "'"; |
| | | // 统一关键字模糊查询 |
| | | 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 (!severityLevel.empty()) { |
| | | query << " AND a.severity_level = '" << severityLevel << "'"; |
| | | } |
| | | if (!deviceName.empty()) { |
| | | query << " AND d.device_name LIKE '%" << deviceName << "%'"; |
| | | } |
| | | if (!unitName.empty()) { |
| | | query << " AND u.unit_name LIKE '%" << unitName << "%'"; |
| | | } |
| | | if (!description.empty()) { |
| | | query << " AND a.description LIKE '%" << description << "%'"; |
| | | } |
| | | |
| | | // 时间条件 |
| | | if (!startTime.empty()) { |
| | | query << " AND a.start_time >= '" << startTime << "'"; |
| | | } |
| | |
| | | } |
| | | |
| | | // 分页设置 |
| | | int offset = (pageNumber - 1) * pageSize; |
| | | query << " ORDER BY a.start_time DESC LIMIT " << pageSize << " OFFSET " << offset; |
| | | int nOffset = (pageNumber - 1) * pageSize; |
| | | query << " ORDER BY a.start_time DESC LIMIT " << pageSize << " OFFSET " << nOffset; |
| | | |
| | | // 查询 |
| | | auto results = m_pDB->fetchResults(query.str()); |
| | | |
| | | // 遍历查询结果,填充 AlarmData 结构体 |
| | |
| | | } |
| | | |
| | | // 获取符合条件的报警总数 |
| | | int AlarmManager::getTotalAlarmCount( |
| | | const std::string& id, |
| | | const std::string& severityLevel, |
| | | const std::string& deviceName, |
| | | const std::string& unitName, |
| | | const std::string& description, |
| | | const std::string& startTime, |
| | | const std::string& endTime) { |
| | | |
| | | int AlarmManager::getTotalAlarmCount(const std::string& keyword, const std::string& startTime, const std::string& endTime) { |
| | | if (!m_pDB) { |
| | | return 0; |
| | | } |
| | | |
| | | std::ostringstream query; |
| | | query << "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"; |
| | | 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 (!id.empty()) { |
| | | query << " AND a.id = '" << id << "'"; |
| | | // 统一关键字模糊查询 |
| | | 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 (!severityLevel.empty()) { |
| | | query << " AND a.severity_level = '" << severityLevel << "'"; |
| | | } |
| | | if (!deviceName.empty()) { |
| | | query << " AND d.device_name LIKE '%" << deviceName << "%'"; |
| | | } |
| | | if (!unitName.empty()) { |
| | | query << " AND u.unit_name LIKE '%" << unitName << "%'"; |
| | | } |
| | | if (!description.empty()) { |
| | | query << " AND a.description LIKE '%" << description << "%'"; |
| | | } |
| | | |
| | | // 时间条件 |
| | | if (!startTime.empty()) { |
| | | query << " AND a.start_time >= '" << startTime << "'"; |
| | | } |
| | |
| | | |
| | | // 读取报警文件 |
| | | bool AlarmManager::readAlarmFile(const std::string& filename) { |
| | | std::ifstream file(filename); |
| | | std::string line; |
| | | bool first_line = true; |
| | | |
| | | std::ifstream file(filename, std::ios::binary); |
| | | if (!file.is_open()) { |
| | | std::cerr << "Error opening file!" << std::endl; |
| | | return false; |
| | | } |
| | | |
| | | while (std::getline(file, line)) { |
| | | 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::string cell; |
| | | AlarmInfo alarm; |
| | | |
| | | std::getline(ss, cell, ','); |
| | | std::getline(ss, alarm.strUnitID, ','); |
| | | std::getline(ss, alarm.strUnitNo, ','); |
| | | std::getline(ss, cell, ','); |
| | | alarm.nAlarmLevel = 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, ','); |
| | | 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; |
| | | if (m_mapAlarm.find(alarm.nAlarmID) == m_mapAlarm.end()) { |
| | | m_mapAlarm[alarm.nAlarmID] = alarm; |
| | | } |
| | | else { |
| | | std::cerr << "Duplicate AlarmID: " << alarm.nAlarmID << std::endl; |
| | | } |
| | | } |
| | | 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; |
| | | } |
| | | } |
| | | |