thresholds: support hysteresis field if supplied

At the moment dbus-sensors that use thresholds use a default hysteresis
of (max - min) * 0.01. If a hysteresis field is specified for a
threshold that is not NaN, use that instead.

Tested by giving a sensor multiple thresholds, with and without
hysteresis, changing the value of the sensor and observing that the
threshold alarms are asserted and deasserted as expected.

Signed-off-by: Rashmica Gupta <rashmica.g@gmail.com>
Change-Id: I9c6c2ef3bb034157b0a6b3bd5c359dae7592d85b
diff --git a/include/Thresholds.hpp b/include/Thresholds.hpp
index af63f72..209d68e 100644
--- a/include/Thresholds.hpp
+++ b/include/Thresholds.hpp
@@ -25,14 +25,17 @@
 };
 struct Threshold
 {
-    Threshold(const Level& lev, const Direction& dir, const double& val,
-              bool write = true) :
+    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), writeable(write)
+        direction(dir), value(val), hysteresis(hysteresis), writeable(write)
     {}
     Level level;
     Direction direction;
     double value;
+    double hysteresis;
     bool writeable;
 
     bool operator==(const Threshold& rhs) const
diff --git a/include/sensor.hpp b/include/sensor.hpp
index 3ac7774..3df7118 100644
--- a/include/sensor.hpp
+++ b/include/sensor.hpp
@@ -230,6 +230,10 @@
             });
         for (auto& threshold : thresholds)
         {
+            if (std::isnan(threshold.hysteresis))
+            {
+                threshold.hysteresis = hysteresisTrigger;
+            }
             std::shared_ptr<sdbusplus::asio::dbus_interface> iface;
             std::string level;
             std::string alarm;
diff --git a/src/Thresholds.cpp b/src/Thresholds.cpp
index c52eee6..0581f21 100644
--- a/src/Thresholds.cpp
+++ b/src/Thresholds.cpp
@@ -100,6 +100,14 @@
             }
         }
 
+        double hysteresis = std::numeric_limits<double>::quiet_NaN();
+        auto hysteresisFind = item.second.find("Hysteresis");
+        if (hysteresisFind != item.second.end())
+        {
+            hysteresis =
+                std::visit(VariantToDoubleVisitor(), hysteresisFind->second);
+        }
+
         auto directionFind = item.second.find("Direction");
         auto severityFind = item.second.find("Severity");
         auto valueFind = item.second.find("Value");
@@ -133,7 +141,7 @@
         }
         double val = std::visit(VariantToDoubleVisitor(), valueFind->second);
 
-        thresholdVector.emplace_back(level, direction, val);
+        thresholdVector.emplace_back(level, direction, val, hysteresis);
     }
     return true;
 }
@@ -305,7 +313,7 @@
                               << " raw data " << sensor->rawValue << "\n";
                 }
             }
-            else if (value < (threshold.value - sensor->hysteresisTrigger))
+            else if (value < (threshold.value - threshold.hysteresis))
             {
                 thresholdChanges.emplace_back(threshold, false, value);
                 ++cHiFalse;
@@ -328,7 +336,7 @@
                               << sensor->rawValue << "\n";
                 }
             }
-            else if (value > (threshold.value + sensor->hysteresisTrigger))
+            else if (value > (threshold.value + threshold.hysteresis))
             {
                 thresholdChanges.emplace_back(threshold, false, value);
                 ++cLoFalse;