Add support for hard and soft shutdown thresholds

Add support for the new SoftShutdown and HardShutdown sensor threshold
D-Bus interfaces.  These are optional, so if they aren't in the JSON
config file then the code won't put them on D-Bus.

At least one of the low or high values needs to be in the JSON for the
interface to be created.  If there is only one, then NaN will be used
for the missing threshold value to indicate 'not applicable' as the
phosphor-dbus-interfaces yaml definition states.

Since these new interfaces are optional, they cannot be base classes of
the VirtualSensor class as the other threshold interface classes were,
so they are members of the class instead.  To keep all of the threshold
classes consistent, the warning and critical threshold objects were also
changed to be members.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I099f83ca085e7febd4416c581a19716a83c9d133
diff --git a/virtualSensor.hpp b/virtualSensor.hpp
index a04a743..e60bb1a 100644
--- a/virtualSensor.hpp
+++ b/virtualSensor.hpp
@@ -4,6 +4,8 @@
 #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>
 
@@ -16,17 +18,28 @@
 {
 
 using Json = nlohmann::json;
+
+template <typename... T>
+using ServerObject = typename sdbusplus::server::object::object<T...>;
+
 using ValueIface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
+using ValueObject = ServerObject<ValueIface>;
 
-using CriticalInterface =
+using CriticalIface =
     sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical;
+using CriticalObject = ServerObject<CriticalIface>;
 
-using WarningInterface =
+using WarningIface =
     sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning;
+using WarningObject = ServerObject<WarningIface>;
 
-using sensorIfaces =
-    sdbusplus::server::object::object<ValueIface, CriticalInterface,
-                                      WarningInterface>;
+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
 {
@@ -67,7 +80,7 @@
     ParamType paramType;
 };
 
-class VirtualSensor : public sensorIfaces
+class VirtualSensor : public ValueObject
 {
   public:
     VirtualSensor() = delete;
@@ -81,20 +94,12 @@
      */
     VirtualSensor(sdbusplus::bus::bus& bus, const char* objPath,
                   const Json& sensorConfig, const std::string& name) :
-        sensorIfaces(bus, objPath),
+        ValueObject(bus, objPath),
         bus(bus), name(name)
     {
-        initVirtualSensor(sensorConfig);
+        initVirtualSensor(sensorConfig, objPath);
     }
 
-    struct Threshold
-    {
-        double criticalHigh;
-        double criticalLow;
-        double warningHigh;
-        double warningLow;
-    };
-
     /** @brief Set sensor value */
     void setSensorValue(double value);
     /** @brief Update sensor at regular intrval */
@@ -119,12 +124,21 @@
     /** @brief The vecops package so the expression can use vectors */
     exprtk::rtl::vecops::package<double> vecopsPackage;
 
+    /** @brief The critical threshold interface object */
+    std::unique_ptr<CriticalObject> criticalIface;
+    /** @brief The warning threshold interface object */
+    std::unique_ptr<WarningObject> warningIface;
+    /** @brief The soft shutdown threshold interface object */
+    std::unique_ptr<SoftShutdownObject> softShutdownIface;
+    /** @brief The hard shutdown threshold interface object */
+    std::unique_ptr<HardShutdownObject> hardShutdownIface;
+
     /** @brief Read config from json object and initialize sensor data
      * for each virtual sensor
      */
-    void initVirtualSensor(const Json& sensorConfig);
-    /** @brief Set Sensor Threshold to D-bus at beginning */
-    void setSensorThreshold(Threshold& sensorThreshold);
+    void initVirtualSensor(const Json& sensorConfig,
+                           const std::string& objPath);
+
     /** @brief Check Sensor threshold and update alarm and log */
     void checkSensorThreshold(const double value);
 };