diff --git a/eqpalg/utility/fb_state_machine.h b/eqpalg/utility/fb_state_machine.h new file mode 100644 index 0000000..da2159f --- /dev/null +++ b/eqpalg/utility/fb_state_machine.h @@ -0,0 +1,122 @@ +// eqpalg/utility/fb_state_machine.h +#pragma once + +#include +#include +#include + +using TimePoint = std::chrono::system_clock::time_point; +using TimeDur = std::chrono::milliseconds; + +/** + * @brief 反馈动作状态枚举 + */ +enum class FbState { + Idle, // 空闲(无活动动作) + Started, // 刚启动(首周期检测到触发条件,下次检查反馈) + InProgress, // 进行中(等待反馈条件满足或超时) + Done, // 反馈条件满足,动作完成 + NotHold, // keep_mode 下触发条件丢失 + Timeout // 超时 +}; + +/** + * @brief FbStateMachine::update() 的返回结构 + */ +struct FbUpdateResult { + FbState state; + bool funVarsNeedReset; // 本周期是否需要标记 fun_vars 重置 +}; + +/** + * @brief 反馈动作状态机 + * + * 替代 ExpBase 中分散的 4 个方法(act_start_done/act_not_hold/act_done/act_timeout) + * 和 4 个布尔标志(act_started_/act_triggered_/feedback_triggered_/feedback_done_)。 + * + * 管理反馈动作的完整生命周期: + * Idle → Started → InProgress → Done/NotHold/Timeout → Idle + * + * 同时负责动作期间的变量快照和累积更新(通过 VarManager 引用)。 + */ +class FbStateMachine { +public: + FbStateMachine() = default; + ~FbStateMachine() = default; + + // ========== 配置 ========== + + /** + * @param keepMode 是否保持模式(触发条件丢失时退出动作) + * @param timeout 超时时间(-32768ms 表示无限制,仅防溢出) + */ + void configure(bool keepMode, TimeDur timeout); + + // ========== 每周期调用 ========== + + /** + * @brief 更新状态机(每个 mon 周期调用一次) + * + * @param actTriggered 前提表达式结果(exp_act_->evaluate() 的布尔值) + * @param now 当前时间 + * @param mm_vars 变量映射(用于快照/累积更新) + * @param tag_count tag 点数量 + * + * @return FbUpdateResult — 新状态 + 是否需要重置 fun_vars + */ + FbUpdateResult update(bool actTriggered, TimePoint now, + std::map& mm_vars, + size_t tag_count); + + /** + * @brief 检查反馈条件(在 update() 返回 InProgress 后调用) + * + * @param fbCondition 反馈表达式结果(exp_feedback_->evaluate() 的布尔值) + * @param now 当前时间 + * @param mm_vars 变量映射 + * + * @return true → 反馈条件满足,转为 Done + * @return false → 继续保持 InProgress + */ + bool checkFeedback(bool fbCondition, TimePoint now, + std::map& mm_vars); + + // ========== 查询 ========== + + bool isActive() const; // Started 或 InProgress + bool isKeepMode() const { return keep_mode_; } + TimePoint actionStartTime() const { return start_time_; } + FbState currentState() const { return state_; } + + // ========== 外部强制重置(PRR=false 时调用)========== + + void forceReset(); + + // ========== 获取 m_timemode(供外部判断报警消息格式)========== + + bool isTimeMode() const { return time_mode_; } + void setTimeMode(bool v) { time_mode_ = v; } + +private: + bool keep_mode_ = false; + TimeDur timeout_ = std::chrono::minutes(10); + FbState state_ = FbState::Idle; + TimePoint start_time_; + bool time_mode_ = false; // 原 ExpBase::m_timemode + + // ========== 内部变量操作(替代分散在 act_* 方法中的变量更新)========== + + void snapshotActionStart(TimePoint now, + std::map& mm_vars, + size_t tag_count); + void updateActionVars(TimePoint now, + std::map& mm_vars, + size_t tag_count); + void recordActionEnd(TimePoint now, + std::map& mm_vars); + void clearActionAccumulators(std::map& mm_vars, + size_t tag_count); + bool isAccumulatorNearOverflow( + const std::map& mm_vars, + size_t tag_count) const; +};