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