alarm_history.h 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #pragma once
  2. #include <string>
  3. #include <vector>
  4. #include <queue>
  5. #include <mutex>
  6. #include <thread>
  7. #include <atomic>
  8. #include <condition_variable>
  9. #include <opencv2/opencv.hpp>
  10. struct AlarmRecord {
  11. int64_t id;
  12. std::string timestamp; // ISO format: "2025-01-15 14:30:22"
  13. int channel;
  14. std::string fence_name;
  15. std::string class_name;
  16. float confidence;
  17. std::string screenshot_path; // relative path like "data/screenshots/1234567890.jpg"
  18. };
  19. // 姿态报警记录
  20. struct PoseAlarmRecord {
  21. int64_t id;
  22. std::string timestamp;
  23. int channel;
  24. std::string action; // 跌倒/倒地/举手呼救/异常蹲坐
  25. float score;
  26. std::string screenshot_path;
  27. };
  28. struct RelayAction {
  29. int64_t id;
  30. std::string timestamp;
  31. std::string source; // fence=围栏报警 / di=输入联动 / manual=手动
  32. std::string detail; // 触发说明
  33. std::string channels; // 动作的输出通道, 逗号分隔, 如 "y01,y03"
  34. };
  35. class AlarmHistory {
  36. public:
  37. AlarmHistory();
  38. ~AlarmHistory();
  39. bool init(const std::string& db_path = "data/alarms.db",
  40. const std::string& screenshot_dir = "data/screenshots");
  41. // 非阻塞: 仅入队, 由后台线程写盘入库
  42. void record(int channel, const std::string& fence_name,
  43. const std::string& class_name, float confidence,
  44. const cv::Mat& frame);
  45. std::vector<AlarmRecord> getAlarms(int limit = 100, int offset = 0,
  46. int channel = -1,
  47. const std::string& start = "",
  48. const std::string& end = "");
  49. int getAlarmCount(int channel = -1,
  50. const std::string& start = "",
  51. const std::string& end = "");
  52. bool deleteAlarm(int64_t id);
  53. void clearAll();
  54. std::string getScreenshotPath(int64_t id);
  55. // ---- 继电器动作历史(与报警共享保留周期) ----
  56. void recordAction(const std::string& source, const std::string& detail,
  57. const std::string& channels);
  58. std::vector<RelayAction> getActions(int limit = 200);
  59. void clearActions();
  60. // ---- 姿态报警历史 ----
  61. void recordPoseAlarm(int channel, const std::string& action, float score,
  62. const cv::Mat& frame);
  63. std::vector<PoseAlarmRecord> getPoseAlarms(int limit = 100, int offset = 0,
  64. int channel = -1,
  65. const std::string& action = "",
  66. const std::string& start = "",
  67. const std::string& end = "");
  68. int getPoseAlarmCount(int channel = -1, const std::string& action = "",
  69. const std::string& start = "", const std::string& end = "");
  70. bool deletePoseAlarm(int64_t id);
  71. void clearPoseAlarms();
  72. void cleanup(int keep_days = 30);
  73. private:
  74. void createTable();
  75. void insertRow(const std::string& timestamp, int channel,
  76. const std::string& fence_name, const std::string& class_name,
  77. float confidence, const std::string& rel_path);
  78. void insertActionRow(const std::string& timestamp, const std::string& source,
  79. const std::string& detail, const std::string& channels);
  80. void insertPoseRow(const std::string& timestamp, int channel,
  81. const std::string& action, float score,
  82. const std::string& rel_path);
  83. void workerLoop();
  84. struct Pending {
  85. std::string timestamp;
  86. int channel;
  87. std::string fence_name;
  88. std::string class_name;
  89. float confidence;
  90. std::string rel_path;
  91. cv::Mat frame;
  92. int kind = 0; // 0=围栏报警 1=姿态报警
  93. std::string action; // 姿态动作
  94. float score = 0.0f; // 姿态得分
  95. };
  96. std::mutex mtx_;
  97. std::string db_path_;
  98. std::string screenshot_dir_;
  99. void* db_ = nullptr; // sqlite3*
  100. std::queue<Pending> pending_;
  101. std::condition_variable pending_cv_;
  102. std::thread worker_;
  103. std::atomic<bool> worker_run_{false};
  104. };