Add SetPointOffset To Refish

This allows adding a threshold as a setpoint offset
so that dynamic thresholds can be used to modify a
setpoint.

Tested: Get and Patch worked

{
    "Oem": {
        "OpenBmc": {
            "Fan": {
                "PidControllers": {
                    "CPU1_DIMM_ABC": {
                        "SetPointOffset": "UpperThresholdCritical"
                    }
                }
            }
        }
    }
}

Change-Id: If515971778a8041aba0ab51da87ec5b29ebc359d
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp
index f59c695..9c250e8 100644
--- a/redfish-core/lib/managers.hpp
+++ b/redfish-core/lib/managers.hpp
@@ -477,7 +477,50 @@
                                     return;
                                 }
                                 data = *inputs;
-                            } // doubles
+                            }
+                            else if (propertyPair.first == "SetPointOffset")
+                            {
+                                const std::string* ptr =
+                                    std::get_if<std::string>(
+                                        &propertyPair.second);
+
+                                if (ptr == nullptr)
+                                {
+                                    BMCWEB_LOG_ERROR << "Field Illegal "
+                                                     << propertyPair.first;
+                                    messages::internalError(asyncResp->res);
+                                    return;
+                                }
+                                // translate from dbus to redfish
+                                if (*ptr == "WarningHigh")
+                                {
+                                    (*config)["SetPointOffset"] =
+                                        "UpperThresholdNonCritical";
+                                }
+                                else if (*ptr == "WarningLow")
+                                {
+                                    (*config)["SetPointOffset"] =
+                                        "LowerThresholdNonCritical";
+                                }
+                                else if (*ptr == "CriticalHigh")
+                                {
+                                    (*config)["SetPointOffset"] =
+                                        "UpperThresholdCritical";
+                                }
+                                else if (*ptr == "CriticalLow")
+                                {
+                                    (*config)["SetPointOffset"] =
+                                        "LowerThresholdCritical";
+                                }
+                                else
+                                {
+                                    BMCWEB_LOG_ERROR << "Value Illegal "
+                                                     << *ptr;
+                                    messages::internalError(asyncResp->res);
+                                    return;
+                                }
+                            }
+                            // doubles
                             else if (propertyPair.first ==
                                          "FFGainCoefficient" ||
                                      propertyPair.first == "FFOffCoefficient" ||
@@ -715,6 +758,7 @@
         std::optional<std::vector<std::string>> inputs;
         std::optional<std::vector<std::string>> outputs;
         std::map<std::string, std::optional<double>> doubles;
+        std::optional<std::string> setpointOffset;
         if (!redfish::json_util::readJson(
                 it.value(), response->res, "Inputs", inputs, "Outputs", outputs,
                 "Zones", zones, "FFGainCoefficient",
@@ -724,10 +768,10 @@
                 "ILimitMin", doubles["ILimitMin"], "OutLimitMax",
                 doubles["OutLimitMax"], "OutLimitMin", doubles["OutLimitMin"],
                 "PCoefficient", doubles["PCoefficient"], "SetPoint",
-                doubles["SetPoint"], "SlewNeg", doubles["SlewNeg"], "SlewPos",
-                doubles["SlewPos"], "PositiveHysteresis",
-                doubles["PositiveHysteresis"], "NegativeHysteresis",
-                doubles["NegativeHysteresis"]))
+                doubles["SetPoint"], "SetPointOffset", setpointOffset,
+                "SlewNeg", doubles["SlewNeg"], "SlewPos", doubles["SlewPos"],
+                "PositiveHysteresis", doubles["PositiveHysteresis"],
+                "NegativeHysteresis", doubles["NegativeHysteresis"]))
         {
             BMCWEB_LOG_ERROR << "Line:" << __LINE__ << ", Illegal Property "
                              << it.value().dump();
@@ -784,6 +828,34 @@
             }
         }
 
+        if (setpointOffset)
+        {
+            // translate between redfish and dbus names
+            if (*setpointOffset == "UpperThresholdNonCritical")
+            {
+                output["SetPointOffset"] = std::string("WarningLow");
+            }
+            else if (*setpointOffset == "LowerThresholdNonCritical")
+            {
+                output["SetPointOffset"] = std::string("WarningHigh");
+            }
+            else if (*setpointOffset == "LowerThresholdCritical")
+            {
+                output["SetPointOffset"] = std::string("CriticalLow");
+            }
+            else if (*setpointOffset == "UpperThresholdCritical")
+            {
+                output["SetPointOffset"] = std::string("CriticalHigh");
+            }
+            else
+            {
+                BMCWEB_LOG_ERROR << "Invalid setpointoffset "
+                                 << *setpointOffset;
+                messages::invalidObject(response->res, it.key());
+                return CreatePIDRet::fail;
+            }
+        }
+
         // doubles
         for (const auto& pairs : doubles)
         {