综合平台编程器项目的远程存储
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 

113 rader
3.4 KiB

  1. #include "alarm_service.h"
  2. #include "domain/alarm_model.h"
  3. #include "domain/register_repository.h"
  4. #include "project_service.h"
  5. #include <algorithm>
  6. AlarmService::AlarmService(
  7. const ProjectService &project_service,
  8. RegisterRepository &repository)
  9. : project_service_(project_service),
  10. repository_(repository)
  11. {
  12. }
  13. void AlarmService::refresh()
  14. {
  15. // 每次刷新只根据当前读回值增删记录,不会把通信失败误判为报警解除
  16. const auto now = std::chrono::system_clock::now();
  17. for (const AlarmDefinition &definition
  18. : project_service_.project().alarmDefinitions)
  19. {
  20. // 空值表示寄存器读取失败;保留原记录,等待下一轮成功读回
  21. const std::optional<bool> active = evaluate(definition);
  22. if (!active.has_value())
  23. {
  24. continue;
  25. }
  26. // 同一报警定义在当前会话中最多保留一条活动记录
  27. const auto current = std::find_if(
  28. records_.begin(), records_.end(),
  29. [&definition](const AlarmRecord &record)
  30. {
  31. return record.definitionId == definition.id;
  32. });
  33. if (*active && current == records_.end())
  34. {
  35. // 首次检测到触发时创建未确认记录,并置于列表头部
  36. records_.insert(
  37. records_.begin(),
  38. AlarmRecord{definition.id, definition.message, false, now});
  39. }
  40. else if (!*active && current != records_.end())
  41. {
  42. // 条件恢复后立即移除对应记录,下一次再次触发会生成新记录
  43. records_.erase(current);
  44. }
  45. }
  46. }
  47. bool AlarmService::acknowledge(const std::string &definition_id)
  48. {
  49. const auto record = std::find_if(
  50. records_.begin(), records_.end(),
  51. [&definition_id](const AlarmRecord &candidate)
  52. {
  53. return candidate.definitionId == definition_id;
  54. });
  55. if (record == records_.end())
  56. {
  57. return false;
  58. }
  59. record->acknowledged = true;
  60. return true;
  61. }
  62. void AlarmService::reset()
  63. {
  64. records_.clear();
  65. }
  66. const std::vector<AlarmRecord> &AlarmService::records() const
  67. {
  68. return records_;
  69. }
  70. std::optional<bool> AlarmService::evaluate(
  71. const AlarmDefinition &definition) const
  72. {
  73. if (definition.condition == AlarmCondition::MOn
  74. || definition.condition == AlarmCondition::MOff)
  75. {
  76. // M ON/OFF 共用一次位读取;读取失败时保留旧记录
  77. const BitReadResult value = repository_.readBit(definition.address);
  78. if (!value.succeeded)
  79. {
  80. return std::nullopt;
  81. }
  82. return definition.condition == AlarmCondition::MOn
  83. ? value.value : !value.value;
  84. }
  85. // DHigh 和 DLow 报警读取 D 字,比较方向由定义中的条件决定
  86. const WordReadResult value = repository_.readWord(definition.address);
  87. if (!value.succeeded)
  88. {
  89. // 通信或仓库读取失败不等同于报警解除
  90. return std::nullopt;
  91. }
  92. if (definition.condition == AlarmCondition::DHigh)
  93. {
  94. // 达到阈值即触发高限报警
  95. return value.value >= definition.threshold;
  96. }
  97. if (definition.condition == AlarmCondition::DLow)
  98. {
  99. // 降到阈值即触发低限报警
  100. return value.value <= definition.threshold;
  101. }
  102. // 防御未来新增但尚未实现的报警条件
  103. return std::nullopt;
  104. }