// #include // #include // #include // #include // #include // #include // #include // // ==================== 观察者接口 ==================== // 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 // observer) { // std::lock_guard lock(mtx_); // observers_[eventType].push_back(observer); // } // // 移除观察者 // void removeObserver(std::weak_ptr target) { // std::lock_guard 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> toNotify; // { // std::lock_guard 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>> // 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 { 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(data); // std::cout << "[" << name_ << "] 温度更新: " << *temp << "°C\n"; // } // } // private: // std::string name_; // }; // // ==================== 具体观察者:报警器(拉模型示例)==================== // class TemperatureAlarm : public IObserver, public // std::enable_shared_from_this { 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(data); if // (sensor->getTemperature() > threshold_) { // std::cout << "! 警报 ! 温度超过阈值: " << threshold_ << // "°C\n"; // } // } // } // private: // float threshold_; // }; // // ==================== 主函数 ==================== // int main() { // // 创建主题 // TemperatureSensor sensor; // // 创建观察者(使用智能指针) // auto display1 = std::make_shared("主控屏"); // auto display2 = std::make_shared("备用屏"); // auto alarm = std::make_shared(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(display2)); // std::cout << "\n---- 第三次更新(移除备用屏后)----\n"; // sensor.setTemperature(38.0f); // return 0; // } // #include // #include // #include // #include // #include // #include // #include // #include // #include // #include // #include // #include // #include // //#include "UDT1.h" // //#include // #include "incFileName.h" // #include // #include // //#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 ¤t) { // 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 ¤t = ::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) = // "<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(std::time(0))); // Seed for // randomness while (1) { // a += count + 1; // ss.clear(); // tagValues.clear(); // sq1.clear(); // a = static_cast(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 // #include // #include // #include // #include // int main() { // std::map mm_vars; // mm_vars["tag1"] = 0; // std::string exp_str = "ln(3)"; // // std::string exp_str = "XOR(0,0)"; // std::unique_ptr exp_ptr = // std::make_unique(exp_str, &mm_vars); // std::cout << "tag1:" << mm_vars["tag1"] << ",exp str:" << exp_str // << ",exp value:" << exp_ptr->evaluate() << std::endl; // } // #include // #include // #include // 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 // #include // #include // using std::cout; // using std::endl; // using std::string; // using std::vector; // int main() { // vector m_tag = {"tag1", "tag2", "tag3", "tag5"}; // VarsCache var_cache; // var_cache.init(5, 30); // cout << var_cache.dumps() << std::endl; // return 0; // } // #include // #include // #include // 对于 std::setfill 和 std::setw // #include // #include // 对于 std::stringstream // #include // // 方案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; // 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(now_steady - last_steady_).count(); // auto system_diff = // std::chrono::duration(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( // 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( // std::chrono::duration(total_elapsed + 0.05)); // while (MonotonicRawClock::now() < target) { // // 忙等待,更高精度 // } // } // return 0; // } // #include // #include // #include // 对于 std::setfill 和 std::setw // #include // #include // 对于 std::stringstream // #include // // 辅助函数:格式化当前系统时间 // 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( // 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(end - start); // std::cout << current_time_string(true) << "|耗时: " << duration.count() // << " ms" << std::endl; // return 0; // } // // 检查你的系统如何实现 steady_clock // #include // #include // 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::nanoseconds(ts.tv_sec * 1000000000LL + ts.tv_nsec) // ); // std::cout << "Diff: " << // std::chrono::duration_cast(t1 - t2).count() << // " ns" << stdendl; // return 0; // } #include #include #include // 报警信息结构 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 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 #include 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; }