|
- #include "alarm_service.h"
-
- #include "domain/alarm_model.h"
- #include "domain/register_repository.h"
- #include "project_service.h"
-
- #include <algorithm>
-
- 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<bool> 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<AlarmRecord> &AlarmService::records() const
- {
- return records_;
- }
-
- std::optional<bool> 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;
- }
|