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