blob: 6338290a37b97cabad623aed47456493b6a0c6d3 [file] [log] [blame]
#pragma once
#include "Utils.hpp"
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <nlohmann/json.hpp>
#include <list>
#include <memory>
#include <string>
#include <utility>
#include <vector>
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<double>::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 TimerUsed, boost::asio::steady_timer>;
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<Sensor>& weakSensor,
const Threshold& threshold, bool assert,
double assertValue);
boost::asio::io_context& io;
std::list<TimerPair> timers;
};
bool parseThresholdsFromConfig(
const SensorData& sensorData,
std::vector<thresholds::Threshold>& 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<thresholds::Threshold>& thresholdVector,
const std::string& inputPath, const double& scaleFactor,
const double& offset = 0,
const double& hysteresis = std::numeric_limits<double>::quiet_NaN());
struct ThresholdDefinition
{
Level level;
uint8_t sevOrder;
const char* levelName;
};
constexpr static std::array<thresholds::ThresholdDefinition, 5> 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<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(const std::weak_ptr<Sensor>& weakSensor,
ThresholdTimer& thresholdTimer);
} // namespace thresholds