Chassis: Power: Support get PowerSupply and Voltages
sensors information.

cherry-picked from:
 https://github.com/ampere-openbmc/bmcweb/commit/a20f8b17c1efb92b9a8e95e8867d945bc6177804

Sensor module adds sensorType:"power" to retrieve power supply sensor
information.
This applicable to Power schema version 1.2.1

Limit:
- Not retrieve PowerControl information yet.
- Need to get UpperThresholdFatal and LowerThresholdFatal value.

Tested: Browser and redfishtool
Command test: redfishtool -A Basic -S Always --rhost=$bmc_ip -u
$bmc_user -p $bmc_password Chassis -I 1 Power

Redmine ID: #2145.

Change-Id: Ifd4a7495c216f894f46610c02d3e8a8e3988dfaa
Signed-off-by: Tung Vu <tung.vu@amperecomputing.com>

Chassis: Thermal and Power: Correct @odata.id information

cherry-picked from:
 https://github.com/ampere-openbmc/bmcweb/commit/ae95b0db60e5e680819c9f9b0c6d61caf66b14cf

Allocate @odata.id of schema in correct way.
Sensor module is general interface not used for specific schema.

Tested: Browser and redfishtool
Command test:
- redfishtool -A Basic -S Always --rhost=$bmc_ip -u $bmc_user -p
  $bmc_password Chassis -I 1 Power
- redfishtool -A Basic -S Always --rhost=$bmc_ip -u $bmc_user -p
  $bmc_password Chassis -I 1 Thermal

Redmine ID: #2145 & #2146

Change-Id: I265bbb366c323f39fb6d4ac4f7cccfed4382e98d
Signed-off-by: Tung Vu <tung.vu@amperecomputing.com>

Chassis: Correct @odata.id for specific Chassis sub-node.

cherry-picked from:
 https://github.com/ampere-openbmc/bmcweb/commit/3eaa53a395ad9275042893413cbefc78f52310e5

Currently there are Thermal and Power sub-nodes of Chassis node, correct
@odata.id information for each sub-node in JSON payload.

Tested: Browser and redfishtool
Command test:
- redfishtool -A Basic -S Always --rhost=$bmc_ip -u $bmc_user -p
  $bmc_password Chassis Thermal -I 1
- redfishtool -A Basic -S Always --rhost=$bmc_ip -u $bmc_user -p
  $bmc_password Chassis Power -I 1

Change-Id: I2f831ed40926e85c0b6d1cfa7d759eb0b9321daa
Signed-off-by: Tung Vu <tung.vu@amperecomputing.com>
Signed-off-by: Jennifer Lee <jennifer1.lee@intel.com>
diff --git a/redfish-core/include/redfish.hpp b/redfish-core/include/redfish.hpp
index 3aef06a..4627aa6 100644
--- a/redfish-core/include/redfish.hpp
+++ b/redfish-core/include/redfish.hpp
@@ -21,6 +21,7 @@
 #include "../lib/log_services.hpp"
 #include "../lib/managers.hpp"
 #include "../lib/network_protocol.hpp"
+#include "../lib/power.hpp"
 #include "../lib/redfish_sessions.hpp"
 #include "../lib/roles.hpp"
 #include "../lib/service_root.hpp"
@@ -60,6 +61,7 @@
         nodes.emplace_back(std::make_unique<Thermal>(app));
         nodes.emplace_back(std::make_unique<ManagerCollection>(app));
         nodes.emplace_back(std::make_unique<Manager>(app));
+        nodes.emplace_back(std::make_unique<Power>(app));
         nodes.emplace_back(std::make_unique<ChassisCollection>(app));
         nodes.emplace_back(std::make_unique<Chassis>(app));
         nodes.emplace_back(std::make_unique<UpdateService>(app));
diff --git a/redfish-core/lib/chassis.hpp b/redfish-core/lib/chassis.hpp
index 6615760..cec62d5 100644
--- a/redfish-core/lib/chassis.hpp
+++ b/redfish-core/lib/chassis.hpp
@@ -212,6 +212,22 @@
                             asyncResp->res.jsonValue["Thermal"] = {
                                 {"@odata.id", "/redfish/v1/Chassis/" +
                                                   chassisId + "/Thermal"}};
+                            // Power object
+                            asyncResp->res.jsonValue["Power"] = {
+                                {"@odata.id", "/redfish/v1/Chassis/" +
+                                                  chassisId + "/Power"}};
+
+                            // TODO: An array of references to computer systems
+                            // contained in this chassis.
+                            // res.jsonValue["Links"]["ComputerSystems"]
+                            // =
+                            //                          {{{"@odata.id",
+                            //                          "/redfish/v1/Systems/1"}}};
+                            // An array of references to the Managers
+                            // responsible for managing this chassis.
+                            // res.jsonValue["Links"]["ManagedBy"] =
+                            //                        {{{"@odata.id",
+                            //                        "/redfish/v1/Managers/1"}}};
                         },
                         connectionName, path, "org.freedesktop.DBus.Properties",
                         "GetAll",
diff --git a/redfish-core/lib/power.hpp b/redfish-core/lib/power.hpp
new file mode 100644
index 0000000..dc291f1
--- /dev/null
+++ b/redfish-core/lib/power.hpp
@@ -0,0 +1,71 @@
+/*
+// Copyright (c) 2018 Intel Corporation
+// Copyright (c) 2018 Ampere Computing LLC
+/
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
+#pragma once
+
+#include "node.hpp"
+#include "sensors.hpp"
+
+namespace redfish
+{
+
+class Power : public Node
+{
+  public:
+    Power(CrowApp& app) :
+        Node((app), "/redfish/v1/Chassis/<str>/Power/", std::string())
+    {
+        Node::json["@odata.type"] = "#Power.v1_2_1.Power";
+        Node::json["@odata.context"] = "/redfish/v1/$metadata#Power.Power";
+        Node::json["Id"] = "Power";
+        Node::json["Name"] = "Power";
+
+        entityPrivileges = {
+            {boost::beast::http::verb::get, {{"Login"}}},
+            {boost::beast::http::verb::head, {{"Login"}}},
+            {boost::beast::http::verb::patch, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::put, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::delete_, {{"ConfigureManager"}}},
+            {boost::beast::http::verb::post, {{"ConfigureManager"}}}};
+    }
+
+  private:
+    void doGet(crow::Response& res, const crow::Request& req,
+               const std::vector<std::string>& params) override
+    {
+        if (params.size() != 1)
+        {
+            res.result(boost::beast::http::status::internal_server_error);
+            res.end();
+            return;
+        }
+        const std::string& chassis_name = params[0];
+
+        Node::json["@odata.id"] =
+            "/redfish/v1/Chassis/" + chassis_name + "/Power";
+        res.jsonValue = Node::json;
+        auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
+            res, chassis_name,
+            std::initializer_list<const char*>{
+                "/xyz/openbmc_project/sensors/voltage",
+                "/xyz/openbmc_project/sensors/power"},
+            "Power");
+        // TODO Need to retrieve Power Control information.
+        getChassisData(sensorAsyncResp);
+    }
+};
+
+} // namespace redfish
diff --git a/redfish-core/lib/sensors.hpp b/redfish-core/lib/sensors.hpp
index 8b876a5..8b829be 100644
--- a/redfish-core/lib/sensors.hpp
+++ b/redfish-core/lib/sensors.hpp
@@ -47,9 +47,10 @@
 {
   public:
     SensorsAsyncResp(crow::Response& response, const std::string& chassisId,
-                     const std::initializer_list<const char*> types) :
-        res(response),
-        chassisId(chassisId), types(types)
+                     const std::initializer_list<const char*> types,
+                     const std::string& subNode) :
+        chassisId(chassisId),
+        res(response), types(types), chassisSubNode(subNode)
     {
         res.jsonValue["@odata.id"] =
             "/redfish/v1/Chassis/" + chassisId + "/Thermal";
@@ -75,6 +76,7 @@
     crow::Response& res;
     std::string chassisId{};
     const std::vector<const char*> types;
+    std::string chassisSubNode{};
 };
 
 /**
@@ -320,6 +322,10 @@
         unit = "ReadingVolts";
         sensor_json["@odata.type"] = "#Power.v1_0_0.Voltage";
     }
+    else if (sensorType == "power")
+    {
+        unit = "LastPowerOutputWatts";
+    }
     else
     {
         BMCWEB_LOG_ERROR << "Redfish cannot map object type for " << sensorName;
@@ -339,6 +345,8 @@
     properties.emplace_back("xyz.openbmc_project.Sensor.Threshold.Critical",
                             "CriticalLow", "LowerThresholdCritical");
 
+    // TODO Need to get UpperThresholdFatal and LowerThresholdFatal
+
     if (sensorType == "temperature")
     {
         properties.emplace_back("xyz.openbmc_project.Sensor.Value", "MinValue",
@@ -510,8 +518,9 @@
                                 tempArray.push_back(
                                     {{"@odata.id",
                                       "/redfish/v1/Chassis/" +
-                                          SensorsAsyncResp->chassisId +
-                                          "/Thermal#/" + fieldName + "/" +
+                                          SensorsAsyncResp->chassisId + "/" +
+                                          SensorsAsyncResp->chassisSubNode +
+                                          "#/" + fieldName + "/" +
                                           std::to_string(tempArray.size())}});
                                 nlohmann::json& sensorJson = tempArray.back();
 
diff --git a/redfish-core/lib/thermal.hpp b/redfish-core/lib/thermal.hpp
index 0f4e840..cbc45e1 100644
--- a/redfish-core/lib/thermal.hpp
+++ b/redfish-core/lib/thermal.hpp
@@ -54,13 +54,21 @@
         const std::string& chassisName = params[0];
 
         res.jsonValue = Node::json;
-        auto asyncResp = std::make_shared<SensorsAsyncResp>(
+
+        Node::json["@odata.id"] =
+            "/redfish/v1/Chassis/" + chassisName + "/Thermal";
+
+        res.jsonValue = Node::json;
+        auto sensorAsyncResp = std::make_shared<SensorsAsyncResp>(
             res, chassisName,
             std::initializer_list<const char*>{
                 "/xyz/openbmc_project/sensors/fan",
                 "/xyz/openbmc_project/sensors/temperature",
-                "/xyz/openbmc_project/sensors/fan_pwm"});
-        getChassisData(asyncResp);
+                "/xyz/openbmc_project/sensors/fan_pwm"},
+            "Thermal");
+
+        // TODO Need to get Chassis Redundancy information.
+        getChassisData(sensorAsyncResp);
     }
 };