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