Support threshold hysteresis
Add support for a hysteresis value on the warning high/low and critical
high/low sensor thresholds. On the high thresholds, this requires the
sensor value to dip below the (threshold - hysteresis) value before the
alarm clears, and on the low thresholds it has to go above (threshold +
hysteresis).
These are optional fields in the configuration JSON and will default to
zero if not present, which results in the previous behavior of not
having a hysteresis at all.
Tested: with IBM's Ambient_Virtual_Temp sensor. When changing the value
above a high threshold and then back below the threshold, we only see
the alarm deasserted when the temp is below (threshold - hysteresis).
Change-Id: Ied1d40def94e1b66cf4ec8826799bada4e6236ab
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
diff --git a/thresholds.hpp b/thresholds.hpp
index aa77f7f..96486d3 100644
--- a/thresholds.hpp
+++ b/thresholds.hpp
@@ -23,8 +23,33 @@
template <typename T>
struct Threshold;
+struct Hysteresis
+{
+ double highHysteresis;
+ double lowHysteresis;
+ auto getHighHysteresis()
+ {
+ return this->highHysteresis;
+ }
+
+ auto getLowHysteresis()
+ {
+ return this->lowHysteresis;
+ }
+
+ auto setHighHysteresis(double value)
+ {
+ this->highHysteresis = value;
+ }
+
+ auto setLowHysteresis(double value)
+ {
+ this->lowHysteresis = value;
+ }
+};
+
template <>
-struct Threshold<WarningObject> : public WarningObject
+struct Threshold<WarningObject> : public WarningObject, public Hysteresis
{
static constexpr auto name = "Warning";
using WarningObject::WarningObject;
@@ -76,7 +101,7 @@
};
template <>
-struct Threshold<CriticalObject> : public CriticalObject
+struct Threshold<CriticalObject> : public CriticalObject, public Hysteresis
{
static constexpr auto name = "Critical";
using CriticalObject::CriticalObject;
@@ -128,7 +153,9 @@
};
template <>
-struct Threshold<SoftShutdownObject> : public SoftShutdownObject
+struct Threshold<SoftShutdownObject> :
+ public SoftShutdownObject,
+ public Hysteresis
{
static constexpr auto name = "SoftShutdown";
using SoftShutdownObject::SoftShutdownObject;
@@ -180,7 +207,9 @@
};
template <>
-struct Threshold<HardShutdownObject> : public HardShutdownObject
+struct Threshold<HardShutdownObject> :
+ public HardShutdownObject,
+ public Hysteresis
{
static constexpr auto name = "HardShutdown";
using HardShutdownObject::HardShutdownObject;
@@ -232,10 +261,14 @@
};
template <>
-struct Threshold<PerformanceLossObject> : public PerformanceLossObject
+struct Threshold<PerformanceLossObject> :
+ public PerformanceLossObject,
+ public Hysteresis
{
static constexpr auto name = "PerformanceLoss";
using PerformanceLossObject::PerformanceLossObject;
+ double performanceLossHighHysteresis;
+ double performanceLossLowHysteresis;
auto high()
{
diff --git a/virtualSensor.cpp b/virtualSensor.cpp
index 4e9f50a..0f27019 100644
--- a/virtualSensor.cpp
+++ b/virtualSensor.cpp
@@ -18,6 +18,7 @@
static constexpr auto vsThresholdsIfaceSuffix = ".Thresholds";
static constexpr std::array<const char*, 1> calculationIfaces = {
"xyz.openbmc_project.Configuration.ModifiedMedian"};
+static constexpr auto defaultHysteresis = 0;
using namespace phosphor::logging;
@@ -185,6 +186,13 @@
auto threshold = getThresholdType(direction, severity);
thresholds[threshold] = value;
+
+ auto hysteresis =
+ getNumberFromConfig<double>(propertyMap, "Hysteresis", false);
+ if (hysteresis != std::numeric_limits<double>::quiet_NaN())
+ {
+ thresholds[threshold + "Hysteresis"] = hysteresis;
+ }
}
void VirtualSensor::parseConfigInterface(const PropertyMap& propertyMap,
@@ -507,6 +515,10 @@
"CriticalHigh", std::numeric_limits<double>::quiet_NaN()));
criticalIface->criticalLow(threshold.value(
"CriticalLow", std::numeric_limits<double>::quiet_NaN()));
+ criticalIface->setHighHysteresis(
+ threshold.value("CriticalHighHysteresis", defaultHysteresis));
+ criticalIface->setLowHysteresis(
+ threshold.value("CriticalLowHysteresis", defaultHysteresis));
}
if (threshold.contains("WarningHigh") || threshold.contains("WarningLow"))
@@ -518,6 +530,10 @@
"WarningHigh", std::numeric_limits<double>::quiet_NaN()));
warningIface->warningLow(threshold.value(
"WarningLow", std::numeric_limits<double>::quiet_NaN()));
+ warningIface->setHighHysteresis(
+ threshold.value("WarningHighHysteresis", defaultHysteresis));
+ warningIface->setLowHysteresis(
+ threshold.value("WarningLowHysteresis", defaultHysteresis));
}
if (threshold.contains("HardShutdownHigh") ||
@@ -530,6 +546,10 @@
"HardShutdownHigh", std::numeric_limits<double>::quiet_NaN()));
hardShutdownIface->hardShutdownLow(threshold.value(
"HardShutdownLow", std::numeric_limits<double>::quiet_NaN()));
+ hardShutdownIface->setHighHysteresis(
+ threshold.value("HardShutdownHighHysteresis", defaultHysteresis));
+ hardShutdownIface->setLowHysteresis(
+ threshold.value("HardShutdownLowHysteresis", defaultHysteresis));
}
if (threshold.contains("SoftShutdownHigh") ||
@@ -542,6 +562,10 @@
"SoftShutdownHigh", std::numeric_limits<double>::quiet_NaN()));
softShutdownIface->softShutdownLow(threshold.value(
"SoftShutdownLow", std::numeric_limits<double>::quiet_NaN()));
+ softShutdownIface->setHighHysteresis(
+ threshold.value("SoftShutdownHighHysteresis", defaultHysteresis));
+ softShutdownIface->setLowHysteresis(
+ threshold.value("SoftShutdownLowHysteresis", defaultHysteresis));
}
if (threshold.contains("PerformanceLossHigh") ||
@@ -554,6 +578,10 @@
"PerformanceLossHigh", std::numeric_limits<double>::quiet_NaN()));
perfLossIface->performanceLossLow(threshold.value(
"PerformanceLossLow", std::numeric_limits<double>::quiet_NaN()));
+ perfLossIface->setHighHysteresis(threshold.value(
+ "PerformanceLossHighHysteresis", defaultHysteresis));
+ perfLossIface->setLowHysteresis(
+ threshold.value("PerformanceLossLowHysteresis", defaultHysteresis));
}
}
diff --git a/virtualSensor.hpp b/virtualSensor.hpp
index b4fd815..3b47fd6 100644
--- a/virtualSensor.hpp
+++ b/virtualSensor.hpp
@@ -199,8 +199,9 @@
static constexpr auto tname = T::element_type::name;
auto alarmHigh = threshold->alarmHigh();
+ auto highHysteresis = threshold->getHighHysteresis();
if ((!alarmHigh && value >= threshold->high()) ||
- (alarmHigh && value < threshold->high()))
+ (alarmHigh && value < (threshold->high() - highHysteresis)))
{
if (!alarmHigh)
{
@@ -220,8 +221,9 @@
}
auto alarmLow = threshold->alarmLow();
+ auto lowHysteresis = threshold->getLowHysteresis();
if ((!alarmLow && value <= threshold->low()) ||
- (alarmLow && value > threshold->low()))
+ (alarmLow && value > (threshold->low() + lowHysteresis)))
{
if (!alarmLow)
{