#include "alarm_service.h" #include "domain/alarm_model.h" #include "domain/register_repository.h" #include "project_service.h" #include AlarmService::AlarmService( const ProjectService &project_service, RegisterRepository &repository) : project_service_(project_service), repository_(repository) { } void AlarmService::refresh() { // 每次刷新只根据当前读回值增删记录,不会把通信失败误判为报警解除 const auto now = std::chrono::system_clock::now(); for (const AlarmDefinition &definition : project_service_.project().alarmDefinitions) { // 空值表示寄存器读取失败;保留原记录,等待下一轮成功读回 const std::optional active = evaluate(definition); if (!active.has_value()) { continue; } // 同一报警定义在当前会话中最多保留一条活动记录 const auto current = std::find_if( records_.begin(), records_.end(), [&definition](const AlarmRecord &record) { return record.definitionId == definition.id; }); if (*active && current == records_.end()) { // 首次检测到触发时创建未确认记录,并置于列表头部 records_.insert( records_.begin(), AlarmRecord{definition.id, definition.message, false, now}); } else if (!*active && current != records_.end()) { // 条件恢复后立即移除对应记录,下一次再次触发会生成新记录 records_.erase(current); } } } bool AlarmService::acknowledge(const std::string &definition_id) { const auto record = std::find_if( records_.begin(), records_.end(), [&definition_id](const AlarmRecord &candidate) { return candidate.definitionId == definition_id; }); if (record == records_.end()) { return false; } record->acknowledged = true; return true; } void AlarmService::reset() { records_.clear(); } const std::vector &AlarmService::records() const { return records_; } std::optional AlarmService::evaluate( const AlarmDefinition &definition) const { if (definition.condition == AlarmCondition::MOn || definition.condition == AlarmCondition::MOff) { // M ON/OFF 共用一次位读取;读取失败时保留旧记录 const BitReadResult value = repository_.readBit(definition.address); if (!value.succeeded) { return std::nullopt; } return definition.condition == AlarmCondition::MOn ? value.value : !value.value; } // DHigh 和 DLow 报警读取 D 字,比较方向由定义中的条件决定 const WordReadResult value = repository_.readWord(definition.address); if (!value.succeeded) { // 通信或仓库读取失败不等同于报警解除 return std::nullopt; } if (definition.condition == AlarmCondition::DHigh) { // 达到阈值即触发高限报警 return value.value >= definition.threshold; } if (definition.condition == AlarmCondition::DLow) { // 降到阈值即触发低限报警 return value.value <= definition.threshold; } // 防御未来新增但尚未实现的报警条件 return std::nullopt; }