Refactor the threshold checking code

Use threshold template classes so the same code can be used to check
each type of threshold.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I04dfed24a60b30254b9f2dbb26c5cb048a03ab5a
diff --git a/thresholds.hpp b/thresholds.hpp
new file mode 100644
index 0000000..31c30e8
--- /dev/null
+++ b/thresholds.hpp
@@ -0,0 +1,190 @@
+#pragma once
+
+#include <xyz/openbmc_project/Sensor/Threshold/Critical/server.hpp>
+#include <xyz/openbmc_project/Sensor/Threshold/HardShutdown/server.hpp>
+#include <xyz/openbmc_project/Sensor/Threshold/SoftShutdown/server.hpp>
+#include <xyz/openbmc_project/Sensor/Threshold/Warning/server.hpp>
+
+namespace phosphor::virtualSensor
+{
+
+template <typename... T>
+using ServerObject = typename sdbusplus::server::object::object<T...>;
+
+using CriticalIface =
+    sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical;
+using CriticalObject = ServerObject<CriticalIface>;
+
+using WarningIface =
+    sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning;
+using WarningObject = ServerObject<WarningIface>;
+
+using SoftShutdownIface =
+    sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::SoftShutdown;
+using SoftShutdownObject = ServerObject<SoftShutdownIface>;
+
+using HardShutdownIface =
+    sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::HardShutdown;
+using HardShutdownObject = ServerObject<HardShutdownIface>;
+
+template <typename T>
+struct Threshold
+{};
+
+template <>
+struct Threshold<WarningObject>
+{
+  public:
+    static double high(WarningObject* iface)
+    {
+        return iface->warningHigh();
+    }
+    static double low(WarningObject* iface)
+    {
+        return iface->warningLow();
+    }
+
+    static bool alarmHigh(WarningObject* iface)
+    {
+        return iface->warningAlarmHigh();
+    }
+
+    static bool alarmLow(WarningObject* iface)
+    {
+        return iface->warningAlarmLow();
+    }
+
+    static void alarmHigh(WarningObject* iface, bool value)
+    {
+        iface->warningAlarmHigh(value);
+    }
+
+    static void alarmLow(WarningObject* iface, bool value)
+    {
+        iface->warningAlarmLow(value);
+    }
+
+    static const char* name()
+    {
+        return "Warning";
+    }
+};
+
+template <>
+struct Threshold<CriticalObject>
+{
+  public:
+    static double high(CriticalObject* iface)
+    {
+        return iface->criticalHigh();
+    }
+    static double low(CriticalObject* iface)
+    {
+        return iface->criticalLow();
+    }
+
+    static bool alarmHigh(CriticalObject* iface)
+    {
+        return iface->criticalAlarmHigh();
+    }
+
+    static bool alarmLow(CriticalObject* iface)
+    {
+        return iface->criticalAlarmLow();
+    }
+
+    static void alarmHigh(CriticalObject* iface, bool value)
+    {
+        iface->criticalAlarmHigh(value);
+    }
+
+    static void alarmLow(CriticalObject* iface, bool value)
+    {
+        iface->criticalAlarmLow(value);
+    }
+
+    static const char* name()
+    {
+        return "Critical";
+    }
+};
+
+template <>
+struct Threshold<SoftShutdownObject>
+{
+  public:
+    static double high(SoftShutdownObject* iface)
+    {
+        return iface->softShutdownHigh();
+    }
+    static double low(SoftShutdownObject* iface)
+    {
+        return iface->softShutdownLow();
+    }
+
+    static bool alarmHigh(SoftShutdownObject* iface)
+    {
+        return iface->softShutdownAlarmHigh();
+    }
+
+    static bool alarmLow(SoftShutdownObject* iface)
+    {
+        return iface->softShutdownAlarmLow();
+    }
+
+    static void alarmHigh(SoftShutdownObject* iface, bool value)
+    {
+        iface->softShutdownAlarmHigh(value);
+    }
+
+    static void alarmLow(SoftShutdownObject* iface, bool value)
+    {
+        iface->softShutdownAlarmLow(value);
+    }
+
+    static const char* name()
+    {
+        return "SoftShutdown";
+    }
+};
+
+template <>
+struct Threshold<HardShutdownObject>
+{
+  public:
+    static double high(HardShutdownObject* iface)
+    {
+        return iface->hardShutdownHigh();
+    }
+    static double low(HardShutdownObject* iface)
+    {
+        return iface->hardShutdownLow();
+    }
+
+    static bool alarmHigh(HardShutdownObject* iface)
+    {
+        return iface->hardShutdownAlarmHigh();
+    }
+
+    static bool alarmLow(HardShutdownObject* iface)
+    {
+        return iface->hardShutdownAlarmLow();
+    }
+
+    static void alarmHigh(HardShutdownObject* iface, bool value)
+    {
+        iface->hardShutdownAlarmHigh(value);
+    }
+
+    static void alarmLow(HardShutdownObject* iface, bool value)
+    {
+        iface->hardShutdownAlarmLow(value);
+    }
+
+    static const char* name()
+    {
+        return "HardShutdown";
+    }
+};
+
+} // namespace phosphor::virtualSensor
diff --git a/virtualSensor.cpp b/virtualSensor.cpp
index a731a15..74b04f7 100644
--- a/virtualSensor.cpp
+++ b/virtualSensor.cpp
@@ -223,165 +223,6 @@
     ValueIface::value(value);
 }
 
-void VirtualSensor::checkSensorThreshold(const double value)
-{
-    if (warningIface)
-    {
-        if (value >= warningIface->warningHigh())
-        {
-            if (!warningIface->warningAlarmHigh())
-            {
-                warningIface->warningAlarmHigh(true);
-                log<level::ERR>("ASSERT: Virtual Sensor has exceeded "
-                                "warning high threshold",
-                                entry("NAME = %s", name.c_str()));
-            }
-        }
-        else if (warningIface->warningAlarmHigh())
-        {
-            warningIface->warningAlarmHigh(false);
-            log<level::INFO>("DEASSERT: Virtual Sensor is under "
-                             "warning high threshold",
-                             entry("NAME = %s", name.c_str()));
-        }
-
-        if (value <= warningIface->warningLow())
-        {
-            if (!warningIface->warningAlarmLow())
-            {
-                warningIface->warningAlarmLow(true);
-                log<level::ERR>("ASSERT: Virtual Sensor is under "
-                                "warning low threshold",
-                                entry("NAME = %s", name.c_str()));
-            }
-        }
-        else if (warningIface->warningAlarmLow())
-        {
-            warningIface->warningAlarmLow(false);
-            log<level::INFO>("DEASSERT: Virtual Sensor is above "
-                             "warning low threshold",
-                             entry("NAME = %s", name.c_str()));
-        }
-    }
-
-    if (criticalIface)
-    {
-        if (value >= criticalIface->criticalHigh())
-        {
-            if (!criticalIface->criticalAlarmHigh())
-            {
-                criticalIface->criticalAlarmHigh(true);
-                log<level::ERR>("ASSERT: Virtual Sensor has exceeded "
-                                "critical high threshold",
-                                entry("NAME = %s", name.c_str()));
-            }
-        }
-        else if (criticalIface->criticalAlarmHigh())
-        {
-            criticalIface->criticalAlarmHigh(false);
-            log<level::INFO>("DEASSERT: Virtual Sensor is under "
-                             "critical high threshold",
-                             entry("NAME = %s", name.c_str()));
-        }
-
-        if (value <= criticalIface->criticalLow())
-        {
-            if (!criticalIface->criticalAlarmLow())
-            {
-                criticalIface->criticalAlarmLow(true);
-                log<level::ERR>("ASSERT: Virtual Sensor is under "
-                                "critical low threshold",
-                                entry("NAME = %s", name.c_str()));
-            }
-        }
-        else if (criticalIface->criticalAlarmLow())
-        {
-            criticalIface->criticalAlarmLow(false);
-            log<level::INFO>("DEASSERT: Virtual Sensor is above "
-                             "critical low threshold",
-                             entry("NAME = %s", name.c_str()));
-        }
-    }
-
-    if (softShutdownIface)
-    {
-        if (value >= softShutdownIface->softShutdownHigh())
-        {
-            if (!softShutdownIface->softShutdownAlarmHigh())
-            {
-                softShutdownIface->softShutdownAlarmHigh(true);
-                log<level::ERR>("ASSERT: Virtual Sensor has exceeded "
-                                "softShutdown high threshold",
-                                entry("NAME = %s", name.c_str()));
-            }
-        }
-        else if (softShutdownIface->softShutdownAlarmHigh())
-        {
-            softShutdownIface->softShutdownAlarmHigh(false);
-            log<level::INFO>("DEASSERT: Virtual Sensor is under "
-                             "softShutdown high threshold",
-                             entry("NAME = %s", name.c_str()));
-        }
-
-        if (value <= softShutdownIface->softShutdownLow())
-        {
-            if (!softShutdownIface->softShutdownAlarmLow())
-            {
-                softShutdownIface->softShutdownAlarmLow(true);
-                log<level::ERR>("ASSERT: Virtual Sensor is under "
-                                "softShutdown low threshold",
-                                entry("NAME = %s", name.c_str()));
-            }
-        }
-        else if (softShutdownIface->softShutdownAlarmLow())
-        {
-            softShutdownIface->softShutdownAlarmLow(false);
-            log<level::INFO>("DEASSERT: Virtual Sensor is above "
-                             "softShutdown low threshold",
-                             entry("NAME = %s", name.c_str()));
-        }
-    }
-
-    if (hardShutdownIface)
-    {
-        if (value >= hardShutdownIface->hardShutdownHigh())
-        {
-            if (!hardShutdownIface->hardShutdownAlarmHigh())
-            {
-                hardShutdownIface->hardShutdownAlarmHigh(true);
-                log<level::ERR>("ASSERT: Virtual Sensor has exceeded "
-                                "hardShutdown high threshold",
-                                entry("NAME = %s", name.c_str()));
-            }
-        }
-        else if (hardShutdownIface->hardShutdownAlarmHigh())
-        {
-            hardShutdownIface->hardShutdownAlarmHigh(false);
-            log<level::INFO>("DEASSERT: Virtual Sensor is under "
-                             "hardShutdown high threshold",
-                             entry("NAME = %s", name.c_str()));
-        }
-
-        if (value <= hardShutdownIface->hardShutdownLow())
-        {
-            if (!hardShutdownIface->hardShutdownAlarmLow())
-            {
-                hardShutdownIface->hardShutdownAlarmLow(true);
-                log<level::ERR>("ASSERT: Virtual Sensor is under "
-                                "hardShutdown low threshold",
-                                entry("NAME = %s", name.c_str()));
-            }
-        }
-        else if (hardShutdownIface->hardShutdownAlarmLow())
-        {
-            hardShutdownIface->hardShutdownAlarmLow(false);
-            log<level::INFO>("DEASSERT: Virtual Sensor is above "
-                             "hardShutdown low threshold",
-                             entry("NAME = %s", name.c_str()));
-        }
-    }
-}
-
 void VirtualSensor::updateVirtualSensor()
 {
     for (auto& param : paramMap)
@@ -406,8 +247,11 @@
     if (DEBUG)
         std::cout << "Sensor value is " << val << "\n";
 
-    /* Check sensor threshold and log required message */
-    checkSensorThreshold(val);
+    /* Check sensor thresholds and log required message */
+    checkThresholds(val, warningIface.get());
+    checkThresholds(val, criticalIface.get());
+    checkThresholds(val, softShutdownIface.get());
+    checkThresholds(val, hardShutdownIface.get());
 }
 
 /** @brief Parsing Virtual Sensor config JSON file  */
diff --git a/virtualSensor.hpp b/virtualSensor.hpp
index e60bb1a..13e342c 100644
--- a/virtualSensor.hpp
+++ b/virtualSensor.hpp
@@ -1,12 +1,11 @@
 #include "dbusSensor.hpp"
 #include "exprtkTools.hpp"
+#include "thresholds.hpp"
+
+#include <fmt/format.h>
 
 #include <nlohmann/json.hpp>
 #include <sdbusplus/bus.hpp>
-#include <xyz/openbmc_project/Sensor/Threshold/Critical/server.hpp>
-#include <xyz/openbmc_project/Sensor/Threshold/HardShutdown/server.hpp>
-#include <xyz/openbmc_project/Sensor/Threshold/SoftShutdown/server.hpp>
-#include <xyz/openbmc_project/Sensor/Threshold/Warning/server.hpp>
 #include <xyz/openbmc_project/Sensor/Value/server.hpp>
 
 #include <map>
@@ -25,22 +24,6 @@
 using ValueIface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
 using ValueObject = ServerObject<ValueIface>;
 
-using CriticalIface =
-    sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical;
-using CriticalObject = ServerObject<CriticalIface>;
-
-using WarningIface =
-    sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning;
-using WarningObject = ServerObject<WarningIface>;
-
-using SoftShutdownIface =
-    sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::SoftShutdown;
-using SoftShutdownObject = ServerObject<SoftShutdownIface>;
-
-using HardShutdownIface =
-    sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::HardShutdown;
-using HardShutdownObject = ServerObject<HardShutdownIface>;
-
 class SensorParam
 {
   public:
@@ -140,7 +123,52 @@
                            const std::string& objPath);
 
     /** @brief Check Sensor threshold and update alarm and log */
-    void checkSensorThreshold(const double value);
+    template <typename T>
+    void checkThresholds(double value, T* iface)
+    {
+        if (iface)
+        {
+            if (value >= Threshold<T>::high(iface))
+            {
+                if (!Threshold<T>::alarmHigh(iface))
+                {
+                    Threshold<T>::alarmHigh(iface, true);
+                    log<level::ERR>(fmt::format("ASSERT: {} has exceeded the "
+                                                "{} high threshold",
+                                                name, Threshold<T>::name())
+                                        .c_str());
+                }
+            }
+            else if (Threshold<T>::alarmHigh(iface))
+            {
+                Threshold<T>::alarmHigh(iface, false);
+                log<level::INFO>(fmt::format("DEASSERT: {} is under the "
+                                             "{} high threshold",
+                                             name, Threshold<T>::name())
+                                     .c_str());
+            }
+
+            if (value <= Threshold<T>::low(iface))
+            {
+                if (!Threshold<T>::alarmLow(iface))
+                {
+                    Threshold<T>::alarmLow(iface, true);
+                    log<level::ERR>(fmt::format("ASSERT: {} is under the "
+                                                "{} high threshold",
+                                                name, Threshold<T>::name())
+                                        .c_str());
+                }
+            }
+            else if (Threshold<T>::alarmLow(iface))
+            {
+                Threshold<T>::alarmLow(iface, false);
+                log<level::INFO>(fmt::format("DEASSERT: {} is above the "
+                                             "{} high threshold",
+                                             name, Threshold<T>::name())
+                                     .c_str());
+            }
+        }
+    }
 };
 
 class VirtualSensors