1 #include "numeric_threshold.hpp" 2 3 #include <phosphor-logging/log.hpp> 4 5 NumericThreshold::NumericThreshold( 6 boost::asio::io_context& ioc, const std::string& triggerIdIn, 7 Sensors sensorsIn, 8 std::vector<std::unique_ptr<interfaces::TriggerAction>> actionsIn, 9 Milliseconds dwellTimeIn, numeric::Direction directionIn, 10 double thresholdValueIn, numeric::Type typeIn, 11 std::unique_ptr<interfaces::Clock> clockIn) : 12 ioc(ioc), 13 triggerId(triggerIdIn), actions(std::move(actionsIn)), 14 dwellTime(dwellTimeIn), direction(directionIn), 15 thresholdValue(thresholdValueIn), type(typeIn), clock(std::move(clockIn)) 16 { 17 for (const auto& sensor : sensorsIn) 18 { 19 sensorDetails.emplace(sensor, makeDetails(sensor->getName())); 20 } 21 } 22 23 void NumericThreshold::initialize() 24 { 25 ThresholdOperations().initialize(this); 26 } 27 28 void NumericThreshold::updateSensors(Sensors newSensors) 29 { 30 ThresholdOperations().updateSensors(this, std::move(newSensors)); 31 } 32 33 NumericThreshold::ThresholdDetail& 34 NumericThreshold::getDetails(const interfaces::Sensor& sensor) 35 { 36 return ThresholdOperations().getDetails(this, sensor); 37 } 38 39 std::shared_ptr<NumericThreshold::ThresholdDetail> 40 NumericThreshold::makeDetails(const std::string& sensorName) 41 { 42 return std::make_shared<ThresholdDetail>(sensorName, thresholdValue, false, 43 ioc); 44 } 45 46 void NumericThreshold::sensorUpdated(interfaces::Sensor& sensor, 47 Milliseconds timestamp, double value) 48 { 49 auto& details = getDetails(sensor); 50 auto& [sensorName, prevValue, dwell, timer] = details; 51 bool decreasing = thresholdValue < prevValue && thresholdValue > value; 52 bool increasing = thresholdValue > prevValue && thresholdValue < value; 53 54 if (dwell && (increasing || decreasing)) 55 { 56 timer.cancel(); 57 dwell = false; 58 } 59 if ((direction == numeric::Direction::decreasing && decreasing) || 60 (direction == numeric::Direction::increasing && increasing) || 61 (direction == numeric::Direction::either && (increasing || decreasing))) 62 { 63 startTimer(details, value); 64 } 65 66 prevValue = value; 67 } 68 69 void NumericThreshold::startTimer(NumericThreshold::ThresholdDetail& details, 70 double value) 71 { 72 const auto& sensorName = details.sensorName; 73 auto& dwell = details.dwell; 74 auto& timer = details.timer; 75 76 if (dwellTime == Milliseconds::zero()) 77 { 78 commit(sensorName, value); 79 } 80 else 81 { 82 dwell = true; 83 timer.expires_after(dwellTime); 84 timer.async_wait([this, &sensorName, &dwell, 85 value](const boost::system::error_code ec) { 86 if (ec) 87 { 88 phosphor::logging::log<phosphor::logging::level::DEBUG>( 89 "Timer has been canceled"); 90 return; 91 } 92 commit(sensorName, value); 93 dwell = false; 94 }); 95 } 96 } 97 98 void NumericThreshold::commit(const std::string& sensorName, double value) 99 { 100 Milliseconds timestamp = clock->systemTimestamp(); 101 for (const auto& action : actions) 102 { 103 action->commit(triggerId, std::nullopt, sensorName, timestamp, value); 104 } 105 } 106 107 LabeledThresholdParam NumericThreshold::getThresholdParam() const 108 { 109 return numeric::LabeledThresholdParam(type, dwellTime.count(), direction, 110 thresholdValue); 111 } 112