Implements ThermalMetrics schema

The ThermalMetrics schema is a resource in Redfish version 2022.2[1].
It contains an array of temperature readings.
It is a child of ThermalSubsystem schema[2] and it represents the
thermal metrics of a chassis.
Reading the current value of each temperature sensor and the
corresponding link enumeration will be implemented in the next patch.

This commit implements the Get and Head methods of the Redfish
ThermalMetrics schema and implemented the basic information of Get.

[1] https://www.dmtf.org/sites/default/files/standards/documents/DSP0268_2022.2.pdf
[2] https://redfish.dmtf.org/schemas/v1/ThermalMetrics.v1_0_1.json

Test:
1. Validator passed.
2. doGet method:
"""
curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Chassis/chassis/ThermalSubsystem/ThermalMetrics
{
  "@odata.id": "/redfish/v1/Chassis/chassis/ThermalSubsystem/ThermalMetrics",
  "@odata.type": "#ThermalMetrics.v1_0_1.ThermalMetrics",
  "Id": "ThermalMetrics",
  "Name": "Thermal Metrics",
}
"""
3. A bad chassis ID:
"""
curl -k -H "X-Auth-Token: $token" -X GET https://${bmc}/redfish/v1/Chassis/chassisBAD/ThermalSubsystem/ThermalMetrics
{
  "error": {
    "@Message.ExtendedInfo": [
    {
      "@odata.type": "#Message.v1_1_1.Message",
      "Message": "The requested resource of type Chassis named 'chassisBAD' was not found.",
      "MessageArgs": [
        "Chassis",
        "chassisBAD"
      ],
      "MessageId": "Base.1.13.0.ResourceNotFound",
      "MessageSeverity": "Critical",
      "Resolution": "Provide a valid resource identifier and resubmit the request."
    }
  ],
  "code": "Base.1.13.0.ResourceNotFound",
  "message": "The requested resource of type Chassis named 'chassisBAD' was not found."
  }
}
"""

Signed-off-by: zhanghaicheng <zhanghch05@inspur.com>
Change-Id: Ib4182e7dc6e204371636a33a391e8e2a58dad113
diff --git a/redfish-core/lib/thermal_metrics.hpp b/redfish-core/lib/thermal_metrics.hpp
new file mode 100644
index 0000000..f254118
--- /dev/null
+++ b/redfish-core/lib/thermal_metrics.hpp
@@ -0,0 +1,91 @@
+#pragma once
+
+#include "app.hpp"
+#include "query.hpp"
+#include "registries/privilege_registry.hpp"
+#include "utils/chassis_utils.hpp"
+
+#include <functional>
+#include <memory>
+#include <optional>
+#include <string>
+
+namespace redfish
+{
+inline void
+    doThermalMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                     const std::string& chassisId,
+                     const std::optional<std::string>& validChassisPath)
+{
+    if (!validChassisPath)
+    {
+        messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
+        return;
+    }
+
+    asyncResp->res.addHeader(
+        boost::beast::http::field::link,
+        "</redfish/v1/JsonSchemas/ThermalMetrics/ThermalMetrics.json>; rel=describedby");
+    asyncResp->res.jsonValue["@odata.type"] =
+        "#ThermalMetrics.v1_0_1.ThermalMetrics";
+    asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
+        "/redfish/v1/Chassis/{}/ThermalSubsystem/ThermalMetrics", chassisId);
+    asyncResp->res.jsonValue["Id"] = "ThermalMetrics";
+    asyncResp->res.jsonValue["Name"] = "Thermal Metrics";
+}
+
+inline void handleThermalMetricsHead(
+    App& app, const crow::Request& req,
+    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+    const std::string& chassisId)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+
+    redfish::chassis_utils::getValidChassisPath(
+        asyncResp, chassisId,
+        [asyncResp,
+         chassisId](const std::optional<std::string>& validChassisPath) {
+        if (!validChassisPath)
+        {
+            messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
+            return;
+        }
+        asyncResp->res.addHeader(
+            boost::beast::http::field::link,
+            "</redfish/v1/JsonSchemas/ThermalMetrics/ThermalMetrics.json>; rel=describedby");
+    });
+}
+
+inline void
+    handleThermalMetricsGet(App& app, const crow::Request& req,
+                            const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
+                            const std::string& chassisId)
+{
+    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
+    {
+        return;
+    }
+
+    redfish::chassis_utils::getValidChassisPath(
+        asyncResp, chassisId,
+        std::bind_front(doThermalMetrics, asyncResp, chassisId));
+}
+
+inline void requestRoutesThermalMetrics(App& app)
+{
+    BMCWEB_ROUTE(app,
+                 "/redfish/v1/Chassis/<str>/ThermalSubsystem/ThermalMetrics/")
+        .privileges(redfish::privileges::headThermalMetrics)
+        .methods(boost::beast::http::verb::head)(
+            std::bind_front(handleThermalMetricsHead, std::ref(app)));
+
+    BMCWEB_ROUTE(app,
+                 "/redfish/v1/Chassis/<str>/ThermalSubsystem/ThermalMetrics/")
+        .privileges(redfish::privileges::getThermalMetrics)
+        .methods(boost::beast::http::verb::get)(
+            std::bind_front(handleThermalMetricsGet, std::ref(app)));
+}
+} // namespace redfish