blob: 638a7f523dadf7bce6c7527a862b80ddca22f356 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
zhanghch055ae1f7f2021-03-08 19:04:35 +08003#pragma once
4
5#include "app.hpp"
George Liu6fe87512023-07-20 15:06:37 +08006#include "dbus_utility.hpp"
zhanghch055ae1f7f2021-03-08 19:04:35 +08007#include "query.hpp"
8#include "registries/privilege_registry.hpp"
9#include "utils/chassis_utils.hpp"
George Liu6fe87512023-07-20 15:06:37 +080010#include "utils/json_utils.hpp"
11#include "utils/sensor_utils.hpp"
zhanghch055ae1f7f2021-03-08 19:04:35 +080012
George Liu6fe87512023-07-20 15:06:37 +080013#include <boost/system/error_code.hpp>
14
15#include <array>
zhanghch055ae1f7f2021-03-08 19:04:35 +080016#include <functional>
17#include <memory>
18#include <optional>
19#include <string>
George Liu6fe87512023-07-20 15:06:37 +080020#include <string_view>
zhanghch055ae1f7f2021-03-08 19:04:35 +080021
22namespace redfish
23{
George Liu6fe87512023-07-20 15:06:37 +080024inline void afterGetTemperatureValue(
25 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
26 const std::string& chassisId, const std::string& path,
27 const boost::system::error_code& ec,
28 const dbus::utility::DBusPropertiesMap& valuesDict)
29{
30 if (ec)
31 {
32 if (ec.value() != EBADR)
33 {
34 BMCWEB_LOG_ERROR("DBUS response error for getAllProperties {}",
35 ec.value());
36 messages::internalError(asyncResp->res);
37 }
38 return;
39 }
40
41 nlohmann::json item = nlohmann::json::object();
42
43 /* Don't return an error for a failure to fill in properties from any of
44 * the sensors in the list. Just skip it.
45 */
46 if (sensor_utils::objectExcerptToJson(
47 path, chassisId, sensor_utils::ChassisSubNode::thermalMetricsNode,
48 "temperature", valuesDict, item))
49 {
50 nlohmann::json& temperatureReadings =
51 asyncResp->res.jsonValue["TemperatureReadingsCelsius"];
52 nlohmann::json::array_t* temperatureArray =
53 temperatureReadings.get_ptr<nlohmann::json::array_t*>();
54 if (temperatureArray == nullptr)
55 {
56 BMCWEB_LOG_ERROR("Missing TemperatureReadingsCelsius Json array");
57 messages::internalError(asyncResp->res);
58 return;
59 }
60
61 temperatureArray->emplace_back(std::move(item));
62 asyncResp->res.jsonValue["TemperatureReadingsCelsius@odata.count"] =
63 temperatureArray->size();
64
65 json_util::sortJsonArrayByKey(*temperatureArray, "DataSourceUri");
66 }
67}
68
69inline void handleTemperatureReadingsCelsius(
70 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
71 const std::string& chassisId, const boost::system::error_code& ec,
72 const sensor_utils::SensorServicePathList& sensorsServiceAndPath)
73{
74 if (ec)
75 {
76 if (ec.value() != EBADR)
77 {
78 BMCWEB_LOG_ERROR("DBUS response error for getAssociatedSubTree {}",
79 ec.value());
80 messages::internalError(asyncResp->res);
81 }
82 return;
83 }
84
85 asyncResp->res.jsonValue["TemperatureReadingsCelsius"] =
86 nlohmann::json::array_t();
87 asyncResp->res.jsonValue["TemperatureReadingsCelsius@odata.count"] = 0;
88
89 for (const auto& [service, sensorPath] : sensorsServiceAndPath)
90 {
Ed Tanousdeae6a72024-11-11 21:58:57 -080091 dbus::utility::getAllProperties(
George Liu6fe87512023-07-20 15:06:37 +080092 *crow::connections::systemBus, service, sensorPath,
93 "xyz.openbmc_project.Sensor.Value",
94 [asyncResp, chassisId,
95 sensorPath](const boost::system::error_code& ec1,
96 const dbus::utility::DBusPropertiesMap& properties) {
97 afterGetTemperatureValue(asyncResp, chassisId, sensorPath, ec1,
98 properties);
99 });
100 }
101}
102
103inline void getTemperatureReadingsCelsius(
104 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
105 const std::string& validChassisPath, const std::string& chassisId)
106{
107 constexpr std::array<std::string_view, 1> interfaces = {
108 "xyz.openbmc_project.Sensor.Value"};
109
110 sensor_utils::getAllSensorObjects(
111 validChassisPath, "/xyz/openbmc_project/sensors/temperature",
112 interfaces, 1,
113 std::bind_front(handleTemperatureReadingsCelsius, asyncResp,
114 chassisId));
115}
116
zhanghch055ae1f7f2021-03-08 19:04:35 +0800117inline void
118 doThermalMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
119 const std::string& chassisId,
120 const std::optional<std::string>& validChassisPath)
121{
122 if (!validChassisPath)
123 {
124 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
125 return;
126 }
127
128 asyncResp->res.addHeader(
129 boost::beast::http::field::link,
130 "</redfish/v1/JsonSchemas/ThermalMetrics/ThermalMetrics.json>; rel=describedby");
131 asyncResp->res.jsonValue["@odata.type"] =
132 "#ThermalMetrics.v1_0_1.ThermalMetrics";
133 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
134 "/redfish/v1/Chassis/{}/ThermalSubsystem/ThermalMetrics", chassisId);
135 asyncResp->res.jsonValue["Id"] = "ThermalMetrics";
136 asyncResp->res.jsonValue["Name"] = "Thermal Metrics";
George Liu6fe87512023-07-20 15:06:37 +0800137
138 getTemperatureReadingsCelsius(asyncResp, *validChassisPath, chassisId);
zhanghch055ae1f7f2021-03-08 19:04:35 +0800139}
140
141inline void handleThermalMetricsHead(
142 App& app, const crow::Request& req,
143 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
144 const std::string& chassisId)
145{
146 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
147 {
148 return;
149 }
150
151 redfish::chassis_utils::getValidChassisPath(
152 asyncResp, chassisId,
153 [asyncResp,
154 chassisId](const std::optional<std::string>& validChassisPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400155 if (!validChassisPath)
156 {
157 messages::resourceNotFound(asyncResp->res, "Chassis",
158 chassisId);
159 return;
160 }
161 asyncResp->res.addHeader(
162 boost::beast::http::field::link,
163 "</redfish/v1/JsonSchemas/ThermalMetrics/ThermalMetrics.json>; rel=describedby");
164 });
zhanghch055ae1f7f2021-03-08 19:04:35 +0800165}
166
167inline void
168 handleThermalMetricsGet(App& app, const crow::Request& req,
169 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
170 const std::string& chassisId)
171{
172 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
173 {
174 return;
175 }
176
177 redfish::chassis_utils::getValidChassisPath(
178 asyncResp, chassisId,
179 std::bind_front(doThermalMetrics, asyncResp, chassisId));
180}
181
182inline void requestRoutesThermalMetrics(App& app)
183{
184 BMCWEB_ROUTE(app,
185 "/redfish/v1/Chassis/<str>/ThermalSubsystem/ThermalMetrics/")
186 .privileges(redfish::privileges::headThermalMetrics)
187 .methods(boost::beast::http::verb::head)(
188 std::bind_front(handleThermalMetricsHead, std::ref(app)));
189
190 BMCWEB_ROUTE(app,
191 "/redfish/v1/Chassis/<str>/ThermalSubsystem/ThermalMetrics/")
192 .privileges(redfish::privileges::getThermalMetrics)
193 .methods(boost::beast::http::verb::get)(
194 std::bind_front(handleThermalMetricsGet, std::ref(app)));
195}
196} // namespace redfish