xref: /openbmc/dbus-sensors/src/Thresholds.hpp (revision a327923d)
1 #pragma once
2 
3 #include "Utils.hpp"
4 
5 #include <boost/asio/io_context.hpp>
6 #include <boost/asio/steady_timer.hpp>
7 #include <nlohmann/json.hpp>
8 
9 #include <list>
10 #include <memory>
11 #include <string>
12 #include <utility>
13 #include <vector>
14 
15 struct Sensor;
16 namespace thresholds
17 {
18 enum class Level
19 {
20     WARNING,
21     CRITICAL,
22     PERFORMANCELOSS,
23     SOFTSHUTDOWN,
24     HARDSHUTDOWN,
25     ERROR
26 };
27 enum class Direction
28 {
29     HIGH,
30     LOW,
31     ERROR
32 };
33 struct Threshold
34 {
Thresholdthresholds::Threshold35     Threshold(
36         const Level& lev, const Direction& dir, const double& val,
37         const double hysteresis = std::numeric_limits<double>::quiet_NaN(),
38         bool write = true) :
39         level(lev),
40         direction(dir), value(val), hysteresis(hysteresis), writeable(write)
41     {}
42     Level level;
43     Direction direction;
44     double value;
45     double hysteresis;
46     bool writeable;
47 
operator ==thresholds::Threshold48     bool operator==(const Threshold& rhs) const
49     {
50         return (level == rhs.level && direction == rhs.direction &&
51                 value == rhs.value);
52     }
53 };
54 
55 void assertThresholds(Sensor* sensor, double assertValue,
56                       thresholds::Level level, thresholds::Direction direction,
57                       bool assert);
58 
59 struct TimerUsed
60 {
61     bool used;
62     Level level;
63     Direction direction;
64     bool assert;
65 };
66 
67 using TimerPair = std::pair<struct TimerUsed, boost::asio::steady_timer>;
68 
69 struct ThresholdTimer
70 {
ThresholdTimerthresholds::ThresholdTimer71     explicit ThresholdTimer(boost::asio::io_context& ioService) : io(ioService)
72     {}
73 
hasActiveTimerthresholds::ThresholdTimer74     bool hasActiveTimer(const Threshold& threshold, bool assert)
75     {
76         for (TimerPair& timer : timers)
77         {
78             if (timer.first.used)
79             {
80                 if ((timer.first.level == threshold.level) &&
81                     (timer.first.direction == threshold.direction) &&
82                     (timer.first.assert == assert))
83                 {
84                     return true;
85                 }
86             }
87         }
88         return false;
89     }
90 
stopTimerthresholds::ThresholdTimer91     void stopTimer(const Threshold& threshold, bool assert)
92     {
93         struct TimerUsed timerUsed = {};
94         for (TimerPair& timer : timers)
95         {
96             timerUsed = timer.first;
97             if (timerUsed.used)
98             {
99                 if ((timerUsed.level == threshold.level) &&
100                     (timerUsed.direction == threshold.direction) &&
101                     (timerUsed.assert == assert))
102                 {
103                     timer.second.cancel();
104                 }
105             }
106         }
107     }
108 
109     void startTimer(const std::weak_ptr<Sensor>& weakSensor,
110                     const Threshold& threshold, bool assert,
111                     double assertValue);
112 
113     boost::asio::io_context& io;
114     std::list<TimerPair> timers;
115 };
116 
117 bool parseThresholdsFromConfig(
118     const SensorData& sensorData,
119     std::vector<thresholds::Threshold>& thresholdVector,
120     const std::string* matchLabel = nullptr, const int* sensorIndex = nullptr);
121 
122 // Sensors touched by parseThresholdFromAttr() are forcibly updated with given
123 // parameters, so callers are encouraged to specify a sane hysteresis value for
124 // their HW. For reference, the hysteresis fomula used in Sensor.hpp is:
125 //  hysteresis.trigger = (max_val - min_val) * 0.01
126 bool parseThresholdsFromAttr(
127     std::vector<thresholds::Threshold>& thresholdVector,
128     const std::string& inputPath, const double& scaleFactor,
129     const double& offset = 0,
130     const double& hysteresis = std::numeric_limits<double>::quiet_NaN());
131 
132 struct ThresholdDefinition
133 {
134     Level level;
135     uint8_t sevOrder;
136     const char* levelName;
137 };
138 
139 constexpr static std::array<thresholds::ThresholdDefinition, 5> thresProp = {
140     {{Level::WARNING, 0, "Warning"},
141      {Level::CRITICAL, 1, "Critical"},
142      {Level::PERFORMANCELOSS, 2, "PerformanceLoss"},
143      {Level::SOFTSHUTDOWN, 3, "SoftShutdown"},
144      {Level::HARDSHUTDOWN, 4, "HardShutdown"}}};
145 
146 std::string getInterface(Level level);
147 
148 void persistThreshold(const std::string& path, const std::string& baseInterface,
149                       const thresholds::Threshold& threshold,
150                       std::shared_ptr<sdbusplus::asio::connection>& conn,
151                       size_t thresholdCount, const std::string& label);
152 
153 void updateThresholds(Sensor* sensor);
154 // returns false if a critical threshold has been crossed, true otherwise
155 bool checkThresholds(Sensor* sensor);
156 void checkThresholdsPowerDelay(const std::weak_ptr<Sensor>& weakSensor,
157                                ThresholdTimer& thresholdTimer);
158 
159 } // namespace thresholds
160