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, false, ioc); 47 } 48 49 void DiscreteThreshold::sensorUpdated(interfaces::Sensor& sensor, 50 Milliseconds timestamp, double value) 51 { 52 auto& details = getDetails(sensor); 53 auto& [sensorName, dwell, timer] = details; 54 55 if (dwell && value != numericThresholdValue) 56 { 57 timer.cancel(); 58 dwell = false; 59 } 60 else if (value == numericThresholdValue) 61 { 62 startTimer(details, value); 63 } 64 } 65 66 void DiscreteThreshold::startTimer(DiscreteThreshold::ThresholdDetail& details, 67 double value) 68 { 69 const auto& sensorName = details.sensorName; 70 auto& dwell = details.dwell; 71 auto& timer = details.timer; 72 73 if (dwellTime == Milliseconds::zero()) 74 { 75 commit(sensorName, value); 76 } 77 else 78 { 79 dwell = true; 80 timer.expires_after(dwellTime); 81 timer.async_wait([this, &sensorName, &dwell, 82 value](const boost::system::error_code ec) { 83 if (ec) 84 { 85 phosphor::logging::log<phosphor::logging::level::DEBUG>( 86 "Timer has been canceled"); 87 return; 88 } 89 commit(sensorName, value); 90 dwell = false; 91 }); 92 } 93 } 94 95 void DiscreteThreshold::commit(const std::string& sensorName, double value) 96 { 97 Milliseconds timestamp = clock->systemTimestamp(); 98 for (const auto& action : actions) 99 { 100 action->commit(triggerId, std::cref(name), sensorName, timestamp, 101 thresholdValue); 102 } 103 } 104 105 LabeledThresholdParam DiscreteThreshold::getThresholdParam() const 106 { 107 return discrete::LabeledThresholdParam(name, severity, dwellTime.count(), 108 thresholdValue); 109 } 110 111 std::string DiscreteThreshold::getNonEmptyName(const std::string& nameIn) const 112 { 113 if (nameIn.empty()) 114 { 115 return discrete::severityToString(severity) + " condition"; 116 } 117 return nameIn; 118 } 119