/** * @file TriggerEngine.cpp * @brief Hub-side trigger FSM implementation (web client semantics). */ #include "TriggerEngine.h" #include "AdvancedErrorManagement.h" namespace StreamHub { TriggerEngine::TriggerEngine() : epoch_(0u), state_(kTrigIdle), stopped_(false), prevValue_(0.0), prevValid_(false), trigTime_(0.0), firedPreSec_(0.0), firedPostSec_(0.0), firedValid_(false) { } void TriggerEngine::SetConfig(const TriggerConfig &cfg) { (void) mutex_.FastLock(); config_ = cfg; /* Clamp to web UI bounds */ if (config_.windowSec < 1.0e-4) { config_.windowSec = 1.0e-4; } if (config_.windowSec > 10.0) { config_.windowSec = 10.0; } if (config_.prePercent < 0.0) { config_.prePercent = 0.0; } if (config_.prePercent > 100.0) { config_.prePercent = 100.0; } epoch_++; prevValid_ = false; prevValue_ = 0.0; mutex_.FastUnLock(); } TriggerConfig TriggerEngine::GetConfig() const { (void) mutex_.FastLock(); TriggerConfig ret = config_; mutex_.FastUnLock(); return ret; } uint32 TriggerEngine::GetConfigEpoch() const { (void) mutex_.FastLock(); uint32 ret = epoch_; mutex_.FastUnLock(); return ret; } void TriggerEngine::Arm() { (void) mutex_.FastLock(); state_ = kTrigArmed; prevValid_ = false; prevValue_ = 0.0; mutex_.FastUnLock(); } void TriggerEngine::Disarm() { (void) mutex_.FastLock(); state_ = kTrigIdle; stopped_ = false; prevValid_ = false; prevValue_ = 0.0; firedValid_ = false; mutex_.FastUnLock(); } void TriggerEngine::SetStopped(bool stopped) { (void) mutex_.FastLock(); stopped_ = stopped; mutex_.FastUnLock(); } bool TriggerEngine::GetStopped() const { (void) mutex_.FastLock(); bool ret = stopped_; mutex_.FastUnLock(); return ret; } void TriggerEngine::CheckSample(float64 t, float64 v) { (void) mutex_.FastLock(); if (state_ != kTrigArmed) { mutex_.FastUnLock(); return; } if (!prevValid_) { prevValue_ = v; prevValid_ = true; mutex_.FastUnLock(); return; } const float64 thr = config_.threshold; const bool up = (prevValue_ < thr) && (v >= thr); const bool down = (prevValue_ > thr) && (v <= thr); prevValue_ = v; bool fired = false; switch (config_.edge) { case kEdgeRising: fired = up; break; case kEdgeFalling: fired = down; break; case kEdgeBoth: fired = (up || down); break; default: break; } if (fired) { state_ = kTrigCollecting; trigTime_ = t; /* Latch the window at fire time so later config edits do not * affect this capture (web client snap._preS/_postS). */ firedPreSec_ = config_.windowSec * config_.prePercent / 100.0; firedPostSec_ = config_.windowSec - firedPreSec_; firedValid_ = true; REPORT_ERROR_STATIC(MARTe::ErrorManagement::Information, "TriggerEngine: fired at t=%.6f (pre=%.4fs post=%.4fs)", t, firedPreSec_, firedPostSec_); } mutex_.FastUnLock(); } TrigState TriggerEngine::GetState() const { (void) mutex_.FastLock(); TrigState ret = state_; mutex_.FastUnLock(); return ret; } bool TriggerEngine::GetFiredWindow(float64 &trigTime, float64 &preSec, float64 &postSec) const { (void) mutex_.FastLock(); const bool ok = firedValid_; if (ok) { trigTime = trigTime_; preSec = firedPreSec_; postSec = firedPostSec_; } mutex_.FastUnLock(); return ok; } void TriggerEngine::MarkTriggered() { (void) mutex_.FastLock(); if (state_ == kTrigCollecting) { state_ = kTrigTriggered; } mutex_.FastUnLock(); } } /* namespace StreamHub */