| #pragma once |
| #include <Utils.hpp> |
| #include <boost/asio/deadline_timer.hpp> |
| #include <boost/asio/io_service.hpp> |
| #include <nlohmann/json.hpp> |
| |
| #include <list> |
| #include <memory> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| struct Sensor; |
| namespace thresholds |
| { |
| enum Level |
| { |
| WARNING, |
| CRITICAL |
| }; |
| enum Direction |
| { |
| HIGH, |
| LOW |
| }; |
| struct Threshold |
| { |
| Threshold(const Level& lev, const Direction& dir, const double& val, |
| bool write = true) : |
| level(lev), |
| direction(dir), value(val), writeable(write) |
| {} |
| Level level; |
| Direction direction; |
| double value; |
| 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 TimerUsed, boost::asio::deadline_timer>; |
| |
| struct ThresholdTimer |
| { |
| |
| ThresholdTimer(boost::asio::io_service& ioService, Sensor* sensor) : |
| io(ioService), sensor(sensor) |
| {} |
| |
| 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 Threshold& threshold, bool assert, double assertValue) |
| { |
| struct TimerUsed timerUsed = {}; |
| constexpr const size_t waitTime = 5; |
| TimerPair* pair = nullptr; |
| |
| for (TimerPair& timer : timers) |
| { |
| if (!timer.first.used) |
| { |
| pair = &timer; |
| break; |
| } |
| } |
| if (pair == nullptr) |
| { |
| pair = &timers.emplace_back(timerUsed, |
| boost::asio::deadline_timer(io)); |
| } |
| |
| pair->first.used = true; |
| pair->first.level = threshold.level; |
| pair->first.direction = threshold.direction; |
| pair->first.assert = assert; |
| pair->second.expires_from_now(boost::posix_time::seconds(waitTime)); |
| pair->second.async_wait([this, pair, threshold, assert, |
| assertValue](boost::system::error_code ec) { |
| pair->first.used = false; |
| |
| if (ec == boost::asio::error::operation_aborted) |
| { |
| return; // we're being canceled |
| } |
| if (ec) |
| { |
| |
| std::cerr << "timer error: " << ec.message() << "\n"; |
| |
| return; |
| } |
| if (isPowerOn()) |
| { |
| assertThresholds(sensor, assertValue, threshold.level, |
| threshold.direction, assert); |
| } |
| }); |
| } |
| |
| boost::asio::io_service& io; |
| std::list<TimerPair> timers; |
| Sensor* sensor; |
| }; |
| |
| bool parseThresholdsFromConfig( |
| const SensorData& sensorData, |
| std::vector<thresholds::Threshold>& thresholdVector, |
| const std::string* matchLabel = nullptr); |
| |
| bool parseThresholdsFromAttr(std::vector<thresholds::Threshold>& thresholds, |
| const std::string& inputPath, |
| const double& scaleFactor, |
| const double& offset = 0); |
| bool hasCriticalInterface( |
| const std::vector<thresholds::Threshold>& thresholdVector); |
| |
| bool hasWarningInterface( |
| const std::vector<thresholds::Threshold>& thresholdVector); |
| |
| void persistThreshold(const std::string& baseInterface, const std::string& path, |
| const thresholds::Threshold& threshold, |
| std::shared_ptr<sdbusplus::asio::connection>& 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(Sensor* sensor, ThresholdTimer& thresholdTimer); |
| |
| } // namespace thresholds |