eis/TestProject/play_gruond/main.cpp

879 lines
27 KiB
C++
Raw Normal View History

// #include <iostream>
// #include <vector>
// #include <memory>
// #include <mutex>
// #include <algorithm>
// #include <unordered_map>
// #include <functional>
// // ==================== 观察者接口 ====================
// class IObserver {
// public:
// virtual ~IObserver() = default;
// virtual void update(const std::string& eventType, void* data) = 0; //
// 支持事件类型区分
// };
// // ==================== 主题基类 (线程安全) ====================
// class Observable {
// public:
// virtual ~Observable() = default;
// // 注册观察者(支持事件类型过滤)
// void addObserver(const std::string& eventType, std::weak_ptr<IObserver>
// observer) {
// std::lock_guard<std::mutex> lock(mtx_);
// observers_[eventType].push_back(observer);
// }
// // 移除观察者
// void removeObserver(std::weak_ptr<IObserver> target) {
// std::lock_guard<std::mutex> lock(mtx_);
// for (auto& [type, list] : observers_) {
// list.erase(
// std::remove_if(list.begin(), list.end(),
// [&](const auto& weakObserver) {
// if (auto observer = weakObserver.lock()) {
// return observer == target.lock();
// }
// return false; // 自动清理失效指针
// }),
// list.end()
// );
// }
// }
// protected:
// // 通知特定事件类型的所有观察者(推模型)
// void notify(const std::string& eventType, void* data = nullptr) {
// std::vector<std::weak_ptr<IObserver>> toNotify;
// {
// std::lock_guard<std::mutex> lock(mtx_);
// if (observers_.find(eventType) != observers_.end()) {
// toNotify = observers_[eventType];
// }
// }
// // 遍历通知(自动清理失效观察者)
// auto it = toNotify.begin();
// while (it != toNotify.end()) {
// if (auto observer = it->lock()) {
// observer->update(eventType, data);
// ++it;
// } else {
// it = toNotify.erase(it);
// }
// }
// }
// private:
// std::unordered_map<std::string, std::vector<std::weak_ptr<IObserver>>>
// observers_; mutable std::mutex mtx_;
// };
// // ==================== 具体主题:温度传感器 ====================
// class TemperatureSensor : public Observable {
// public:
// void setTemperature(float temp) {
// temperature_ = temp;
// notify("TEMP_UPDATE", &temperature_); // 推模型传递数据
// }
// // 拉模型支持
// float getTemperature() const { return temperature_; }
// private:
// float temperature_ = 0.0f;
// };
// // ==================== 具体观察者:显示设备 ====================
// class DisplayDevice : public IObserver, public
// std::enable_shared_from_this<DisplayDevice> { public:
// explicit DisplayDevice(const std::string& name) : name_(name) {}
// void subscribeTo(Observable& subject, const std::string& eventType) {
// subject.addObserver(eventType, weak_from_this());
// }
// void update(const std::string& eventType, void* data) override {
// if (eventType == "TEMP_UPDATE") {
// float* temp = static_cast<float*>(data);
// std::cout << "[" << name_ << "] 温度更新: " << *temp << "°C\n";
// }
// }
// private:
// std::string name_;
// };
// // ==================== 具体观察者:报警器(拉模型示例)====================
// class TemperatureAlarm : public IObserver, public
// std::enable_shared_from_this<TemperatureAlarm> { public:
// explicit TemperatureAlarm(float threshold) : threshold_(threshold) {}
// void subscribeTo(TemperatureSensor& sensor) {
// sensor.addObserver("TEMP_UPDATE", weak_from_this());
// }
// void update(const std::string& eventType, void* data) override {
// if (eventType == "TEMP_UPDATE") {
// // 拉模型示例:主动从主题获取数据
// TemperatureSensor* sensor =
// static_cast<TemperatureSensor*>(data); if
// (sensor->getTemperature() > threshold_) {
// std::cout << "! 警报 ! 温度超过阈值: " << threshold_ <<
// "°C\n";
// }
// }
// }
// private:
// float threshold_;
// };
// // ==================== 主函数 ====================
// int main() {
// // 创建主题
// TemperatureSensor sensor;
// // 创建观察者(使用智能指针)
// auto display1 = std::make_shared<DisplayDevice>("主控屏");
// auto display2 = std::make_shared<DisplayDevice>("备用屏");
// auto alarm = std::make_shared<TemperatureAlarm>(35.0f);
// // 注册观察者
// display1->subscribeTo(sensor, "TEMP_UPDATE");
// display2->subscribeTo(sensor, "TEMP_UPDATE");
// alarm->subscribeTo(sensor);
// // 模拟温度变化
// std::cout << "---- 第一次更新 ----\n";
// sensor.setTemperature(25.5f);
// std::cout << "\n---- 第二次更新 ----\n";
// sensor.setTemperature(37.2f); // 触发警报
// // 动态移除观察者
// sensor.removeObserver(std::weak_ptr<IObserver>(display2));
// std::cout << "\n---- 第三次更新(移除备用屏后)----\n";
// sensor.setTemperature(38.0f);
// return 0;
// }
// #include <model/Model2SliceI.h>
// #include <Ice/Ice.h>
// #include <Ice/OutputStream.h>
// #include <Ice/Proxy.h>
// #include <arpa/inet.h>
// #include <dirent.h>
// #include <log4cplus/LOG.h>
// #include <map>
// #include <pace/P99Component.h>
// #include <pace/pace.h>
// #include <string>
// #include <sys/stat.h>
// #include <vector>
// //#include "UDT1.h"
// //#include <boost/type_index.hpp>
// #include "incFileName.h"
// #include <cstdlib>
// #include <ctime>
// //#include "STD/UDT_1.h"
// using namespace iPlature;
// namespace iPlature {
// class EventCallBck : public virtual EventReceiverI {
// public:
// EventCallBck() {}
// ~EventCallBck() {}
// virtual void recvCallBack(const ::Ice::StringSeq &tagNames,
// const ::AP::ByteSeqSeq &tagValues,
// const Ice::Current &current) {
// LOG log("recvCallBack");
// // STD::DSC_MTR::MTR ab;
// short ab = 0;
// for (int i = 0; i < tagNames.size(); i++) {
// log.Info() << "tagName = " << tagNames.at(i) << endl;
// }
// for (int i = 0; i < tagValues.size(); i++) {
// log.DebugHex((void *)&tagValues.at(i).front(),
// (int)tagValues.at(i).size());
// memset(&ab, 0, tagValues.at(i).size());
// memcpy(&ab, &tagValues.at(i).front(), sizeof(2));
// }
// }
// };
// } // namespace iPlature
// using namespace iPlature;
// using namespace std;
// class EventReceiverComponent : public Component {
// public:
// virtual int start() {
// // 创建日志对象
// LOG log("EventReceiverMain");
// // 创建指针
// ptr = new iPlature::EventCallBck();
// std::cout << "ptr" << ptr << endl;
// // 添加指针
// this->add("iPlature/EventCallBck", ptr);
// log.Info() << "add ok " << endl;
// DRSdkConnectParam con;
// // con.szServerIp = "10.25.101.165";
// // con.nServerPort =10087 ;
// con.szServerIp = "192.168.0.12";
// con.nServerPort = 1234;
// con.szServerIpBak = "192.168.0.13";
// con.nServerPortBak = 1234;
// con.flag = 1;
// con.nConnectTimeoutMs = 1000;
// con.nHeartbeatTimeoutMs = 3000;
// DRSdkOption op;
// op.nThreadPoolNum = 10;
// op.nRequestWaitTimeoutMs = 1000;
// const ::Ice::Current &current = ::Ice::emptyCurrent;
// //初始化连接
// ptr->Init(con, op, current);
// log.Info() << "Init ok " << endl;
// ::AP::ByteSeqSeq seq;
// // STD::MTR ab;
// // STD::DSC_MTR::MTR er;
// // log.Debug() << "er size" << sizeof(er) << endl;
// // DSF Name STD.DSC_MTR::MTR
// // C++ Name STD::DSC_MTR::MTR
// std::string objName = "STD::DSC_MTR::MTR";
// Ice::StringSeq ss;
// ss.push_back("STD::TEST1");
// ss.push_back("STD::TEST2");
// ss.push_back("STD::TEST3");
// ss.push_back("STD::TEST4");
// ss.push_back("STD::TEST5");
// // ss.push_back(objName);
// //ͬ同步读
// seq = ptr->readData(ss, current);
// log.Debug() << "readData" << endl;
// short a = 0;
// for (int i = 0; i < seq.size(); i++) {
// ::Ice::ByteSeq sq(sizeof(seq.at(i).size()));
// sq = seq.at(i);
// log.DebugHex((void *)&sq.front(), (int)sq.size());
// memcpy(&a, (void *)&sq.front(), 2);
// std::cout << "a = " << a << endl;
// }
// std::cout << "seq size = " << seq.size() << endl;
// log.Debug() << "seq size = " << seq.size() << endl;
// // ::Ice::ByteSeq sq(sizeof(STD::DSC_MTR::MTR));
// // memcpy((void*)&sq.front(),&er,sizeof(STD::DSC_MTR::MTR));
// // std::cout << "sizeof(STD::DSC_MTR::MTR) =
// "<<sizeof(STD::DSC_MTR::MTR)
// //<< endl;
// //异步读
// ss.clear();
// // ss.push_back("STD::DSC_MTR::MTR");
// ss.push_back("STD::TEST1");
// ss.push_back("STD::TEST2");
// ss.push_back("STD::TEST3");
// ss.push_back("STD::TEST4");
// ss.push_back("STD::TEST5");
// int batchid = ptr->regist(ss, 100, current);
// // short
// a = 5;
// ::AP::ByteSeqSeq tagValues;
// ::Ice::ByteSeq sq1; //(sizeof(aa.O_HMI_STAT_RDY));
// // STD::DSC_MTR::MTR ee;
// int count = 0;
// std::srand(static_cast<unsigned int>(std::time(0))); // Seed for
// randomness while (1) {
// a += count + 1;
// ss.clear();
// tagValues.clear();
// sq1.clear();
// a = static_cast<short>(rand()) / 1000;
// sq1.resize(2);
// memcpy((void *)&sq1.front(), &a, 2);
// tagValues.push_back(sq1);
// sq1.clear();
// sq1.resize(2);
// memcpy((void *)&sq1.front(), &a, 2);
// tagValues.push_back(sq1);
// sq1.clear();
// sq1.resize(2);
// memcpy((void *)&sq1.front(), &a, 2);
// tagValues.push_back(sq1);
// sq1.clear();
// sq1.resize(2);
// memcpy((void *)&sq1.front(), &a, 2);
// tagValues.push_back(sq1);
// sq1.clear();
// sq1.resize(2);
// memcpy((void *)&sq1.front(), &a, 2);
// tagValues.push_back(sq1);
// sq1.clear();
// ss.clear();
// ss.push_back("STD::TEST1");
// ss.push_back("STD::TEST2");
// ss.push_back("STD::TEST3");
// ss.push_back("STD::TEST4");
// ss.push_back("STD::TEST5");
// log.Debug() << "tagValues size = " << tagValues.size() << endl;
// //下发
// int b = ptr->setControlData(ss, tagValues, 5, current);
// log.Info() << "setControlData ok b = " << b << endl;
// log.Info() << "1111" << endl;
// sleep(1);
// count++;
// }
// std::cout << "setControlData ok " << endl;
// }
// private:
// iPlature::EventCallBck *ptr;
// };
// PACE_SERVER_INSTALL(EventReceiverComponent)
// #include "exp_extract.hpp"
// #include "mix_cc/ihyper_db.h"
// #include "mix_cc/json.h"
// #include "mix_cc/matheval/matheval.hpp"
// #include <iomanip>
// #include <iostream>
// #include <map>
// #include <memory>
// #include <string>
// int main() {
// std::map<std::string, double> mm_vars;
// mm_vars["tag1"] = 0;
// std::string exp_str = "ln(3)";
// // std::string exp_str = "XOR(0,0)";
// std::unique_ptr<mix_cc::matheval::Expression> exp_ptr =
// std::make_unique<mix_cc::matheval::Expression>(exp_str, &mm_vars);
// std::cout << "tag1:" << mm_vars["tag1"] << ",exp str:" << exp_str
// << ",exp value:" << exp_ptr->evaluate() << std::endl;
// }
// #include <regex>
// #include <string>
// #include <iostream>
// int extractCTaskNumberRegex(const std::string& input) {
// std::regex pattern(R"(_(\d+)_task$)");
// std::smatch matches;
// if (std::regex_search(input, matches, pattern)) {
// if (matches.size() > 1) { // 索引0是完整匹配索引1是第一个捕获组
// try {
// return std::stoi(matches[1].str());
// } catch (...) {
// return 0;
// }
// }
// }
// return 0;
// }
// // 增强版,可以匹配更多情况
// int extractCTaskNumberRegexEnhanced(const std::string& input) {
// // 匹配任意字符串中的最后一个数字(该数字后面跟下划线和"task"
// std::regex pattern(R"((\d+)(?=_task$))");
// std::smatch matches;
// if (std::regex_search(input, matches, pattern)) {
// try {
// return std::stoi(matches[1].str());
// } catch (...) {
// return 0;
// }
// }
// return 0;
// }
// // 或者更通用的版本,提取最后一个数字部分
// int extractCTaskNumberRegexGeneric(const std::string& input) {
// // 匹配任意位置的数字部分,但通过贪婪匹配获取最后一个
// std::regex pattern(R"((\d+))");
// std::sregex_iterator begin(input.begin(), input.end(), pattern);
// std::sregex_iterator end;
// std::string lastMatch;
// for (auto it = begin; it != end; ++it) {
// lastMatch = (*it)[1].str();
// }
// if (!lastMatch.empty()) {
// try {
// return std::stoi(lastMatch);
// } catch (...) {
// return 0;
// }
// }
// return 0;
// }
// int main() {
// std::string test1 = "12_4_5_task";
// std::string test2 = "a_b_123_task";
// std::string test3 = "test_45_678_task";
// std::cout << extractCTaskNumberRegex(test1) << std::endl; // 输出:
// 5 std::cout << extractCTaskNumberRegexEnhanced(test1) << std::endl; //
// 输出: 5 std::cout << extractCTaskNumberRegexGeneric(test1) << std::endl;
// // 输出: 5
// std::cout << extractCTaskNumberRegex(test2) << std::endl; // 输出:
// 123 std::cout << extractCTaskNumberRegexGeneric(test3) << std::endl; //
// 输出: 678
// return 0;
// }
// #include "VarsCache.hpp"
// #include <iostream>
// #include <string>
// #include <vector>
// using std::cout;
// using std::endl;
// using std::string;
// using std::vector;
// int main() {
// vector<string> m_tag = {"tag1", "tag2", "tag3", "tag5"};
// VarsCache var_cache;
// var_cache.init(5, 30);
// cout << var_cache.dumps() << std::endl;
// return 0;
// }
// #include <chrono>
// #include <ctime>
// #include <iomanip> // 对于 std::setfill 和 std::setw
// #include <iostream>
// #include <sstream> // 对于 std::stringstream
// #include <thread>
// // 方案1使用CLOCK_MONOTONIC_RAW不受NTP和VMware调整
// class MonotonicRawClock {
// public:
// using duration = std::chrono::nanoseconds;
// using rep = duration::rep;
// using period = duration::period;
// using time_point = std::chrono::time_point<MonotonicRawClock>;
// static constexpr bool is_steady = true;
// static time_point now() noexcept {
// timespec ts;
// // CLOCK_MONOTONIC_RAW基于硬件TSC不受时间同步影响
// clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
// return time_point(std::chrono::seconds(ts.tv_sec) +
// std::chrono::nanoseconds(ts.tv_nsec));
// }
// };
// // 方案2混合时钟检测并补偿跳跃
// class RobustTimer {
// private:
// using SteadyClock = std::chrono::steady_clock;
// using SystemClock = std::chrono::system_clock;
// SteadyClock::time_point last_steady_;
// SystemClock::time_point last_system_;
// double estimated_drift_;
// public:
// RobustTimer() : estimated_drift_(0.0) {
// last_steady_ = SteadyClock::now();
// last_system_ = SystemClock::now();
// }
// // 获取经过的时间,自动补偿跳跃
// double elapsed_seconds() {
// auto now_steady = SteadyClock::now();
// auto now_system = SystemClock::now();
// auto steady_diff =
// std::chrono::duration<double>(now_steady - last_steady_).count();
// auto system_diff =
// std::chrono::duration<double>(now_system - last_system_).count();
// // 检测跳跃差异超过10ms
// if (std::abs(steady_diff - system_diff) > 0.01) {
// std::cerr << "检测到时间跳跃: " << (steady_diff - system_diff) * 1000
// << "ms" << std::endl;
// // 使用steady_clock但记录跳跃
// estimated_drift_ += system_diff - steady_diff;
// }
// last_steady_ = now_steady;
// last_system_ = now_system;
// return steady_diff + estimated_drift_;
// }
// };
// // 辅助函数:格式化当前系统时间
// std::string current_time_string(bool with_ms = true) {
// auto now = std::chrono::system_clock::now();
// auto time_t_now = std::chrono::system_clock::to_time_t(now);
// std::tm tm_buf;
// localtime_r(&time_t_now, &tm_buf);
// char buffer[80];
// strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm_buf);
// std::stringstream ss;
// ss << buffer;
// if (with_ms) {
// auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
// now.time_since_epoch()) %
// 1000;
// ss << "." << std::setfill('0') << std::setw(3) << ms.count();
// }
// return ss.str();
// }
// int main() {
// // 使用MonotonicRawClock
// auto start = MonotonicRawClock::now();
// RobustTimer timer;
// double total_elapsed = 0.0;
// while (total_elapsed < 3600.0) { // 运行1小时
// // 你的业务逻辑
// // 获取经过的时间
// double elapsed = timer.elapsed_seconds();
// total_elapsed += elapsed;
// std::cout << current_time_string(true) << "|总运行时间: " <<
// total_elapsed
// << "s, 本次间隔: " << elapsed << "s" << std::endl;
// // 精确等待50ms
// auto target =
// start + std::chrono::duration_cast<MonotonicRawClock::duration>(
// std::chrono::duration<double>(total_elapsed + 0.05));
// while (MonotonicRawClock::now() < target) {
// // 忙等待,更高精度
// }
// }
// return 0;
// }
// #include <chrono>
// #include <ctime>
// #include <iomanip> // 对于 std::setfill 和 std::setw
// #include <iostream>
// #include <sstream> // 对于 std::stringstream
// #include <thread>
// // 辅助函数:格式化当前系统时间
// std::string current_time_string(bool with_ms = true) {
// auto now = std::chrono::system_clock::now();
// auto time_t_now = std::chrono::system_clock::to_time_t(now);
// std::tm tm_buf;
// localtime_r(&time_t_now, &tm_buf);
// char buffer[80];
// strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", &tm_buf);
// std::stringstream ss;
// ss << buffer;
// if (with_ms) {
// auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
// now.time_since_epoch()) %
// 1000;
// ss << "." << std::setfill('0') << std::setw(3) << ms.count();
// }
// return ss.str();
// }
// int main() {
// // 1. 检查标准库是否把 steady_clock 声明为单调的
// std::cout << "is_steady: " << std::chrono::steady_clock::is_steady
// << std::endl;
// // 2. 测试差值是否跳变
// auto start = std::chrono::steady_clock::now();
// std::this_thread::sleep_for(std::chrono::seconds(2)); //
// 等待系统时间跳变发生 auto end = std::chrono::steady_clock::now(); auto
// duration =
// std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
// std::cout << current_time_string(true) << "|耗时: " << duration.count()
// << " ms" << std::endl;
// return 0;
// }
// // 检查你的系统如何实现 steady_clock
// #include <iostream>
// #include <chrono>
// int main() {
// auto start = std::chrono::steady_clock::now();
// // 检查 steady_clock 的底层实现
// std::cout << "steady_clock is_steady: " <<
// std::chrono::steady_clock::is_steady << std::endl;
// // 对比实现
// struct timespec ts;
// clock_gettime(CLOCK_MONOTONIC, &ts);
// auto t1 = std::chrono::steady_clock::now();
// auto t2 = std::chrono::time_point<std::chrono::steady_clock>(
// std::chrono::nanoseconds(ts.tv_sec * 1000000000LL + ts.tv_nsec)
// );
// std::cout << "Diff: " <<
// std::chrono::duration_cast<std::chrono::nanoseconds>(t1 - t2).count() <<
// " ns" << stdendl;
// return 0;
// }
#include <chrono>
#include <iostream>
#include <optional>
// 报警信息结构
struct AlarmInfo {
enum Type { None, Alarm, Timeout } type;
std::string message;
};
// 状态机类
class ExprMonitorSM {
public:
// 构造函数
// hold_mode: 动作表达式是否需要保持为真
// timeout: 超时时间0 表示无超时)
ExprMonitorSM(bool hold_mode, std::chrono::milliseconds timeout =
std::chrono::milliseconds::zero())
: hold_mode_(hold_mode), timeout_(timeout), state_(State::Idle) {}
// 重置状态机(清除所有内部状态)
void reset() {
state_ = State::Idle;
act_trigger_time_ = std::chrono::steady_clock::time_point();
}
// 每个周期调用一次,更新表达式值并获取报警信息
// act: 动作表达式结果
// fb: 反馈表达式结果
// mon: 监控表达式结果
// now: 当前时间(可选,便于测试)
std::optional<AlarmInfo> update(bool act, bool fb, bool mon,
std::chrono::steady_clock::time_point now =
std::chrono::steady_clock::now()) {
// 超时检测(仅当不在空闲状态时)
if (state_ != State::Idle && timeout_.count() > 0) {
if (now - act_trigger_time_ >= timeout_) {
reset();
return AlarmInfo{AlarmInfo::Timeout, "动作触发后超时未收到反馈"};
}
}
switch (state_) {
case State::Idle:
if (act) {
// 动作触发,记录触发时间
act_trigger_time_ = now;
// 根据是否保持进入不同状态
state_ = hold_mode_ ? State::HoldActive : State::WaitForFeedback;
// 注意:同一周期内如果立即满足反馈和监控,继续处理(不会递归,只是走下面的分支)
// 由于状态已改变,下面会根据新状态再次判断 fb / mon
}
break;
case State::WaitForFeedback:
// 非保持模式:不再关心 act只等待反馈或超时
if (fb) {
// 反馈到达,重置触发状态
reset();
// 反馈后检查监控表达式
if (mon) {
return AlarmInfo{AlarmInfo::Alarm, "监控条件满足(反馈后)"};
}
}
break;
case State::HoldActive:
// 保持模式:必须检查 act 是否仍为真
if (!act) {
// 动作条件不再满足,清除触发状态
reset();
} else {
// act 保持为真,检查反馈
if (fb) {
// 反馈到达,重置触发状态
reset();
if (mon) {
return AlarmInfo{AlarmInfo::Alarm,
"监控条件满足(保持模式下反馈后)"};
}
}
}
break;
}
return std::nullopt; // 无报警
}
private:
enum class State { Idle, WaitForFeedback, HoldActive };
bool hold_mode_; // 是否保持模式
std::chrono::milliseconds timeout_; // 超时时间
State state_; // 当前状态
std::chrono::steady_clock::time_point act_trigger_time_; // 动作触发的时间点
};
// ------------------------- 简单测试 -------------------------
#include <cassert>
#include <thread>
void test_non_hold_normal() {
std::cout
<< "\n=== 测试:非保持模式,正常流程(动作触发 → 反馈 → 监控真)===\n";
ExprMonitorSM sm(false, std::chrono::milliseconds(5000));
// 第1周期动作触发
auto alarm = sm.update(true, false, false);
assert(!alarm.has_value());
// 第2周期反馈到达监控为真
alarm = sm.update(false, true, true);
assert(alarm.has_value() && alarm->type == AlarmInfo::Alarm);
std::cout << "报警信息: " << alarm->message << std::endl;
// 状态应已重置,再次触发
alarm = sm.update(true, false, false);
assert(!alarm.has_value());
}
void test_non_hold_timeout() {
std::cout << "\n=== 测试:非保持模式,超时未反馈 ===\n";
ExprMonitorSM sm(false, std::chrono::milliseconds(200));
auto now = std::chrono::steady_clock::now();
// 动作触发
auto alarm = sm.update(true, false, false, now);
assert(!alarm.has_value());
// 模拟超时(过去 300ms
auto later = now + std::chrono::milliseconds(300);
alarm = sm.update(false, false, false, later);
assert(alarm.has_value() && alarm->type == AlarmInfo::Timeout);
std::cout << "报警信息: " << alarm->message << std::endl;
}
void test_hold_normal() {
std::cout << "\n=== 测试:保持模式,动作持续为真 → 反馈 → 监控真 ===\n";
ExprMonitorSM sm(true, std::chrono::milliseconds(5000));
// 第1周期动作触发
auto alarm = sm.update(true, false, false);
assert(!alarm.has_value());
// 第2周期动作仍为真反馈为真监控为真
alarm = sm.update(true, true, true);
assert(alarm.has_value() && alarm->type == AlarmInfo::Alarm);
std::cout << "报警信息: " << alarm->message << std::endl;
}
void test_hold_act_false() {
std::cout << "\n=== 测试:保持模式,动作中途变假,无反馈 ===\n";
ExprMonitorSM sm(true, std::chrono::milliseconds(5000));
// 动作触发
auto alarm = sm.update(true, false, false);
assert(!alarm.has_value());
// 动作变假,状态应退回空闲,不会报警
alarm = sm.update(false, false, false);
assert(!alarm.has_value());
// 重新触发
alarm = sm.update(true, false, false);
assert(!alarm.has_value());
}
void test_hold_timeout() {
std::cout << "\n=== 测试:保持模式,动作持续为真但超时未反馈 ===\n";
ExprMonitorSM sm(true, std::chrono::milliseconds(200));
auto now = std::chrono::steady_clock::now();
// 动作触发
auto alarm = sm.update(true, false, false, now);
assert(!alarm.has_value());
// 动作保持为真,但超过超时时间
auto later = now + std::chrono::milliseconds(300);
alarm = sm.update(true, false, false, later);
assert(alarm.has_value() && alarm->type == AlarmInfo::Timeout);
std::cout << "报警信息: " << alarm->message << std::endl;
}
void test_feedback_without_mon() {
std::cout << "\n=== 测试:反馈为真但监控为假,不报警 ===\n";
ExprMonitorSM sm(false, std::chrono::milliseconds(5000));
// 动作触发
auto alarm = sm.update(true, false, false);
assert(!alarm.has_value());
// 反馈为真,监控为假 → 不报警,但状态重置
alarm = sm.update(false, true, false);
assert(!alarm.has_value());
// 可以再次触发动作
alarm = sm.update(true, false, false);
assert(!alarm.has_value());
}
int main() {
test_non_hold_normal();
test_non_hold_timeout();
test_hold_normal();
test_hold_act_false();
test_hold_timeout();
test_feedback_without_mon();
std::cout << "\n所有测试通过!\n";
return 0;
}