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), direction(dir), value(val), hysteresis(hysteresis), 40 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