eis/eqpalg/utility/fb_state_machine.h
2026-05-15 13:19:19 +08:00

123 lines
4.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// eqpalg/utility/fb_state_machine.h
#pragma once
#include <chrono>
#include <map>
#include <string>
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<std::string, double>& 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<std::string, double>& 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<std::string, double>& mm_vars,
size_t tag_count);
void updateActionVars(TimePoint now,
std::map<std::string, double>& mm_vars,
size_t tag_count);
void recordActionEnd(TimePoint now,
std::map<std::string, double>& mm_vars);
void clearActionAccumulators(std::map<std::string, double>& mm_vars,
size_t tag_count);
bool isAccumulatorNearOverflow(
const std::map<std::string, double>& mm_vars,
size_t tag_count) const;
};