#pragma once #include "Utils.hpp" #include #include #include #include #include #include #include #include struct Sensor; namespace thresholds { enum class Level { WARNING, CRITICAL, PERFORMANCELOSS, SOFTSHUTDOWN, HARDSHUTDOWN, ERROR }; enum class Direction { HIGH, LOW, ERROR }; struct Threshold { Threshold( const Level& lev, const Direction& dir, const double& val, const double hysteresis = std::numeric_limits::quiet_NaN(), bool write = true) : level(lev), direction(dir), value(val), hysteresis(hysteresis), writeable(write) {} Level level; Direction direction; double value; double hysteresis; bool writeable; bool operator==(const Threshold& rhs) const { return (level == rhs.level && direction == rhs.direction && value == rhs.value); } }; void assertThresholds(Sensor* sensor, double assertValue, thresholds::Level level, thresholds::Direction direction, bool assert); struct TimerUsed { bool used; Level level; Direction direction; bool assert; }; using TimerPair = std::pair; struct ThresholdTimer { explicit ThresholdTimer(boost::asio::io_context& ioService) : io(ioService) {} bool hasActiveTimer(const Threshold& threshold, bool assert) { for (TimerPair& timer : timers) { if (timer.first.used) { if ((timer.first.level == threshold.level) && (timer.first.direction == threshold.direction) && (timer.first.assert == assert)) { return true; } } } return false; } void stopTimer(const Threshold& threshold, bool assert) { struct TimerUsed timerUsed = {}; for (TimerPair& timer : timers) { timerUsed = timer.first; if (timerUsed.used) { if ((timerUsed.level == threshold.level) && (timerUsed.direction == threshold.direction) && (timerUsed.assert == assert)) { timer.second.cancel(); } } } } void startTimer(const std::weak_ptr& weakSensor, const Threshold& threshold, bool assert, double assertValue); boost::asio::io_context& io; std::list timers; }; bool parseThresholdsFromConfig( const SensorData& sensorData, std::vector& thresholdVector, const std::string* matchLabel = nullptr, const int* sensorIndex = nullptr); // Sensors touched by parseThresholdFromAttr() are forcibly updated with given // parameters, so callers are encouraged to specify a sane hysteresis value for // their HW. For reference, the hysteresis fomula used in Sensor.hpp is: // hysteresis.trigger = (max_val - min_val) * 0.01 bool parseThresholdsFromAttr( std::vector& thresholdVector, const std::string& inputPath, const double& scaleFactor, const double& offset = 0, const double& hysteresis = std::numeric_limits::quiet_NaN()); struct ThresholdDefinition { Level level; uint8_t sevOrder; const char* levelName; }; constexpr static std::array thresProp = { {{Level::WARNING, 0, "Warning"}, {Level::CRITICAL, 1, "Critical"}, {Level::PERFORMANCELOSS, 2, "PerformanceLoss"}, {Level::SOFTSHUTDOWN, 3, "SoftShutdown"}, {Level::HARDSHUTDOWN, 4, "HardShutdown"}}}; std::string getInterface(Level level); void persistThreshold(const std::string& path, const std::string& baseInterface, const thresholds::Threshold& threshold, std::shared_ptr& conn, size_t thresholdCount, const std::string& label); void updateThresholds(Sensor* sensor); // returns false if a critical threshold has been crossed, true otherwise bool checkThresholds(Sensor* sensor); void checkThresholdsPowerDelay(const std::weak_ptr& weakSensor, ThresholdTimer& thresholdTimer); } // namespace thresholds