xref: /openbmc/telemetry/src/numeric_threshold.cpp (revision b7b7e1b603fd9df56a72547c8048d182a001d647)
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