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)
         {
diff --git a/static/redfish/v1/JsonSchemas/OemManager/index.json b/static/redfish/v1/JsonSchemas/OemManager/index.json
index 5cc0b83..107621e 100644
--- a/static/redfish/v1/JsonSchemas/OemManager/index.json
+++ b/static/redfish/v1/JsonSchemas/OemManager/index.json
@@ -408,6 +408,11 @@
                     "longDescription": "Setpoint for the PID.",
                     "type": "number"
                 },
+                "SetPointOffset": {
+                    "description": "Threshold to take value from and apply to setpoint.",
+                    "longDescription": "Threshold to take value from and apply to setpoint. Valid threshold names are supported.",
+                    "type": "string"
+                },
                 "SlewNeg": {
                     "description": "Negative slew rate for the PID.",
                     "longDescription": "Negative slew rate for the PID.",
@@ -578,4 +583,4 @@
         }
     },
     "title": "#OemManager"
-}
\ No newline at end of file
+}
diff --git a/static/redfish/v1/schema/OemManager_v1.xml b/static/redfish/v1/schema/OemManager_v1.xml
index 164f272..9ae36ca 100644
--- a/static/redfish/v1/schema/OemManager_v1.xml
+++ b/static/redfish/v1/schema/OemManager_v1.xml
@@ -245,6 +245,10 @@
                     <Annotation Term="OData.Description" String="Setpoint for the PID." />
                     <Annotation Term="OData.LongDescription" String="Setpoint for the PID." />
                 </Property>
+                <Property Name="SetPointOffset" Type="Edm.String" Nullable="false">
+                    <Annotation Term="OData.Description" String="Threshold to take value from and apply to setpoint." />
+                    <Annotation Term="OData.LongDescription" String="Threshold to take value from and apply to setpoint. Valid threshold names are supported." />
+                </Property>
                 <Property Name="SlewNeg" Type="Edm.Decimal" Nullable="false">
                     <Annotation Term="OData.Description" String="Negative slew rate for the PID." />
                     <Annotation Term="OData.LongDescription" String="Negative slew rate for the PID." />