xref: /openbmc/telemetry/src/numeric_threshold.cpp (revision f7ea2997ae6b4fad0dc35f9afa9b488d774f2ee1)
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::unique_ptr<interfaces::TriggerAction>> actionsIn,
8     Milliseconds dwellTimeIn, numeric::Direction directionIn,
9     double thresholdValueIn, numeric::Type typeIn) :
10     ioc(ioc),
11     actions(std::move(actionsIn)), dwellTime(dwellTimeIn),
12     direction(directionIn), thresholdValue(thresholdValueIn), type(typeIn)
13 {
14     for (const auto& sensor : sensorsIn)
15     {
16         sensorDetails.emplace(sensor, makeDetails(sensor->getName()));
17     }
18 }
19 
20 void NumericThreshold::initialize()
21 {
22     ThresholdOperations().initialize(this);
23 }
24 
25 void NumericThreshold::updateSensors(Sensors newSensors)
26 {
27     ThresholdOperations().updateSensors(this, std::move(newSensors));
28 }
29 
30 NumericThreshold::ThresholdDetail&
31     NumericThreshold::getDetails(const interfaces::Sensor& sensor)
32 {
33     return ThresholdOperations().getDetails(this, sensor);
34 }
35 
36 std::shared_ptr<NumericThreshold::ThresholdDetail>
37     NumericThreshold::makeDetails(const std::string& sensorName)
38 {
39     return std::make_shared<ThresholdDetail>(sensorName, thresholdValue, false,
40                                              ioc);
41 }
42 
43 void NumericThreshold::sensorUpdated(interfaces::Sensor& sensor,
44                                      Milliseconds timestamp, double value)
45 {
46     auto& details = getDetails(sensor);
47     auto& [sensorName, prevValue, dwell, timer] = details;
48     bool decreasing = thresholdValue < prevValue && thresholdValue > value;
49     bool increasing = thresholdValue > prevValue && thresholdValue < value;
50 
51     if (dwell && (increasing || decreasing))
52     {
53         timer.cancel();
54         dwell = false;
55     }
56     if ((direction == numeric::Direction::decreasing && decreasing) ||
57         (direction == numeric::Direction::increasing && increasing) ||
58         (direction == numeric::Direction::either && (increasing || decreasing)))
59     {
60         startTimer(details, timestamp, value);
61     }
62 
63     prevValue = value;
64 }
65 
66 void NumericThreshold::startTimer(NumericThreshold::ThresholdDetail& details,
67                                   Milliseconds timestamp, 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, timestamp, value);
76     }
77     else
78     {
79         dwell = true;
80         timer.expires_after(dwellTime);
81         timer.async_wait([this, &sensorName, &dwell, timestamp,
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, timestamp, value);
90             dwell = false;
91         });
92     }
93 }
94 
95 void NumericThreshold::commit(const std::string& sensorName,
96                               Milliseconds timestamp, double value)
97 {
98     for (const auto& action : actions)
99     {
100         action->commit(sensorName, timestamp, value);
101     }
102 }
103 
104 LabeledThresholdParam NumericThreshold::getThresholdParam() const
105 {
106     return numeric::LabeledThresholdParam(type, dwellTime.count(), direction,
107                                           thresholdValue);
108 }
109