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