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