xref: /openbmc/telemetry/src/numeric_threshold.cpp (revision 51f0fd501f4b772533271d15cb27d396186a7192)
1 #include "numeric_threshold.hpp"
2 
3 #include <phosphor-logging/log.hpp>
4 
5 NumericThreshold::NumericThreshold(
6     boost::asio::io_context& ioc, Sensors sensorsIn,
7     std::vector<std::string> sensorNames,
8     std::vector<std::unique_ptr<interfaces::TriggerAction>> actionsIn,
9     Milliseconds dwellTimeIn, numeric::Direction direction,
10     double thresholdValueIn) :
11     ioc(ioc),
12     sensors(std::move(sensorsIn)), actions(std::move(actionsIn)),
13     dwellTime(dwellTimeIn), direction(direction),
14     thresholdValue(thresholdValueIn)
15 {
16     details.reserve(sensors.size());
17     for (size_t i = 0; i < sensors.size(); i++)
18     {
19         details.emplace_back(sensorNames[i], thresholdValue, false, ioc);
20     }
21 }
22 
23 NumericThreshold::~NumericThreshold()
24 {}
25 
26 void NumericThreshold::initialize()
27 {
28     for (auto& sensor : sensors)
29     {
30         sensor->registerForUpdates(weak_from_this());
31     }
32 }
33 
34 NumericThreshold::ThresholdDetail&
35     NumericThreshold::getDetails(interfaces::Sensor& sensor)
36 {
37     auto it =
38         std::find_if(sensors.begin(), sensors.end(),
39                      [&sensor](const auto& x) { return &sensor == x.get(); });
40     auto index = std::distance(sensors.begin(), it);
41     return details.at(index);
42 }
43 
44 void NumericThreshold::sensorUpdated(interfaces::Sensor& sensor,
45                                      Milliseconds timestamp)
46 {}
47 
48 void NumericThreshold::sensorUpdated(interfaces::Sensor& sensor,
49                                      Milliseconds timestamp, double value)
50 {
51     auto& [sensorName, prevValue, dwell, timer] = getDetails(sensor);
52     bool decreasing = thresholdValue < prevValue && thresholdValue > value;
53     bool increasing = thresholdValue > prevValue && thresholdValue < value;
54 
55     if (dwell && (increasing || decreasing))
56     {
57         timer.cancel();
58         dwell = false;
59     }
60     if ((direction == numeric::Direction::decreasing && decreasing) ||
61         (direction == numeric::Direction::increasing && increasing) ||
62         (direction == numeric::Direction::either && (increasing || decreasing)))
63     {
64         startTimer(sensorName, timestamp, value, dwell, timer);
65     }
66 
67     prevValue = value;
68 }
69 
70 void NumericThreshold::startTimer(const std::string& sensorName,
71                                   Milliseconds timestamp, double value,
72                                   bool& dwell, boost::asio::steady_timer& timer)
73 {
74     if (dwellTime == Milliseconds::zero())
75     {
76         commit(sensorName, timestamp, value);
77     }
78     else
79     {
80         dwell = true;
81         timer.expires_after(dwellTime);
82         timer.async_wait([this, sensorName, timestamp, value,
83                           &dwell](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, timestamp, value);
91             dwell = false;
92         });
93     }
94 }
95 
96 void NumericThreshold::commit(const std::string& sensorName,
97                               Milliseconds timestamp, double value)
98 {
99     for (const auto& action : actions)
100     {
101         action->commit(sensorName, timestamp, value);
102     }
103 }
104