blob: 09093a3d38d86a002b07e0d3922ec3245d7553e1 [file] [log] [blame]
Ed Tanous40e9b922024-09-10 13:50:16 -07001// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright OpenBMC Authors
George Liua7210022022-10-05 15:44:11 +08003#pragma once
4
5#include "app.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08006#include "async_resp.hpp"
George Liua7210022022-10-05 15:44:11 +08007#include "dbus_utility.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -08008#include "error_messages.hpp"
Ed Tanous539d8c62024-06-19 14:38:27 -07009#include "generated/enums/resource.hpp"
Ed Tanousd7857202025-01-28 15:32:26 -080010#include "http_request.hpp"
11#include "logging.hpp"
George Liua7210022022-10-05 15:44:11 +080012#include "query.hpp"
13#include "registries/privilege_registry.hpp"
14#include "utils/chassis_utils.hpp"
George Liu2b45fb32022-10-05 17:00:00 +080015#include "utils/dbus_utils.hpp"
Hieu Huynhb5190062024-07-11 03:47:21 +000016#include "utils/time_utils.hpp"
George Liua7210022022-10-05 15:44:11 +080017
Ed Tanousd7857202025-01-28 15:32:26 -080018#include <asm-generic/errno.h>
19
20#include <boost/beast/http/field.hpp>
21#include <boost/beast/http/verb.hpp>
George Liu34dfcb92022-10-05 16:47:44 +080022#include <boost/system/error_code.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070023#include <boost/url/format.hpp>
Ed Tanousd7857202025-01-28 15:32:26 -080024#include <nlohmann/json.hpp>
25#include <sdbusplus/unpack_properties.hpp>
Ed Tanousef4c65b2023-04-24 15:28:50 -070026
Ed Tanousd7857202025-01-28 15:32:26 -080027#include <array>
28#include <cstdint>
29#include <functional>
George Liua7210022022-10-05 15:44:11 +080030#include <memory>
31#include <optional>
32#include <string>
Ed Tanousd7857202025-01-28 15:32:26 -080033#include <string_view>
34#include <utility>
George Liua7210022022-10-05 15:44:11 +080035
36namespace redfish
37{
38
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -050039static constexpr std::array<std::string_view, 1> powerSupplyInterface = {
40 "xyz.openbmc_project.Inventory.Item.PowerSupply"};
41
42inline void updatePowerSupplyList(
43 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
44 const std::string& chassisId,
45 const dbus::utility::MapperGetSubTreePathsResponse& powerSupplyPaths)
George Liua7210022022-10-05 15:44:11 +080046{
George Liu00ef5dc2022-10-05 16:27:52 +080047 nlohmann::json& powerSupplyList = asyncResp->res.jsonValue["Members"];
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -050048 for (const std::string& powerSupplyPath : powerSupplyPaths)
49 {
50 std::string powerSupplyName =
51 sdbusplus::message::object_path(powerSupplyPath).filename();
52 if (powerSupplyName.empty())
53 {
54 continue;
55 }
56
57 nlohmann::json item = nlohmann::json::object();
58 item["@odata.id"] = boost::urls::format(
59 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
60 powerSupplyName);
61
62 powerSupplyList.emplace_back(std::move(item));
63 }
George Liu00ef5dc2022-10-05 16:27:52 +080064 asyncResp->res.jsonValue["Members@odata.count"] = powerSupplyList.size();
George Liua7210022022-10-05 15:44:11 +080065}
66
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -050067inline void doPowerSupplyCollection(
68 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
69 const std::string& chassisId, const boost::system::error_code& ec,
70 const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths)
George Liua7210022022-10-05 15:44:11 +080071{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -050072 if (ec)
George Liua7210022022-10-05 15:44:11 +080073 {
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -050074 if (ec.value() != EBADR)
75 {
76 BMCWEB_LOG_ERROR("DBUS response error{}", ec.value());
77 messages::internalError(asyncResp->res);
78 }
George Liua7210022022-10-05 15:44:11 +080079 return;
80 }
George Liua7210022022-10-05 15:44:11 +080081 asyncResp->res.addHeader(
82 boost::beast::http::field::link,
83 "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
84 asyncResp->res.jsonValue["@odata.type"] =
85 "#PowerSupplyCollection.PowerSupplyCollection";
86 asyncResp->res.jsonValue["Name"] = "Power Supply Collection";
Ed Tanousef4c65b2023-04-24 15:28:50 -070087 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
88 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies", chassisId);
George Liua7210022022-10-05 15:44:11 +080089 asyncResp->res.jsonValue["Description"] =
90 "The collection of PowerSupply resource instances.";
George Liu7a2bb2c2023-04-11 10:44:33 +080091 asyncResp->res.jsonValue["Members"] = nlohmann::json::array();
92 asyncResp->res.jsonValue["Members@odata.count"] = 0;
George Liua7210022022-10-05 15:44:11 +080093
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -050094 updatePowerSupplyList(asyncResp, chassisId, subtreePaths);
George Liua7210022022-10-05 15:44:11 +080095}
96
97inline void handlePowerSupplyCollectionHead(
98 App& app, const crow::Request& req,
99 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
100 const std::string& chassisId)
101{
102 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
103 {
104 return;
105 }
106
107 redfish::chassis_utils::getValidChassisPath(
108 asyncResp, chassisId,
109 [asyncResp,
110 chassisId](const std::optional<std::string>& validChassisPath) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400111 if (!validChassisPath)
112 {
113 messages::resourceNotFound(asyncResp->res, "Chassis",
114 chassisId);
115 return;
116 }
117 asyncResp->res.addHeader(
118 boost::beast::http::field::link,
119 "</redfish/v1/JsonSchemas/PowerSupplyCollection/PowerSupplyCollection.json>; rel=describedby");
120 });
George Liua7210022022-10-05 15:44:11 +0800121}
122
123inline void handlePowerSupplyCollectionGet(
124 App& app, const crow::Request& req,
125 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
126 const std::string& chassisId)
127{
128 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
129 {
130 return;
131 }
132
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500133 const std::string reqpath = "/xyz/openbmc_project/inventory";
134
135 dbus::utility::getAssociatedSubTreePathsById(
Myung Bae3f95a272024-03-13 07:32:02 -0700136 chassisId, reqpath, chassisInterfaces, "powered_by",
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500137 powerSupplyInterface,
138 [asyncResp, chassisId](
139 const boost::system::error_code& ec,
140 const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
141 doPowerSupplyCollection(asyncResp, chassisId, ec, subtreePaths);
142 });
George Liua7210022022-10-05 15:44:11 +0800143}
144
145inline void requestRoutesPowerSupplyCollection(App& app)
146{
147 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
148 .privileges(redfish::privileges::headPowerSupplyCollection)
149 .methods(boost::beast::http::verb::head)(
150 std::bind_front(handlePowerSupplyCollectionHead, std::ref(app)));
151
152 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
153 .privileges(redfish::privileges::getPowerSupplyCollection)
154 .methods(boost::beast::http::verb::get)(
155 std::bind_front(handlePowerSupplyCollectionGet, std::ref(app)));
156}
157
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500158inline void afterGetValidPowerSupplyPath(
159 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
160 const std::string& powerSupplyId, const boost::system::error_code& ec,
161 const dbus::utility::MapperGetSubTreeResponse& subtree,
162 const std::function<void(const std::string& powerSupplyPath,
163 const std::string& service)>& callback)
George Liu00ef5dc2022-10-05 16:27:52 +0800164{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500165 if (ec)
166 {
167 if (ec.value() != EBADR)
168 {
169 BMCWEB_LOG_ERROR("DBUS response error{}", ec.value());
170 messages::internalError(asyncResp->res);
171 }
172 return;
173 }
174 for (const auto& [objectPath, service] : subtree)
175 {
176 sdbusplus::message::object_path path(objectPath);
Myung Baed8e2b612024-10-08 12:19:19 -0500177 if (path.filename() == powerSupplyId)
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500178 {
179 callback(path, service.begin()->first);
180 return;
181 }
182 }
George Liu00ef5dc2022-10-05 16:27:52 +0800183
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500184 BMCWEB_LOG_WARNING("Power supply not found: {}", powerSupplyId);
185 messages::resourceNotFound(asyncResp->res, "PowerSupplies", powerSupplyId);
George Liu00ef5dc2022-10-05 16:27:52 +0800186}
187
George Liu34dfcb92022-10-05 16:47:44 +0800188inline void getValidPowerSupplyPath(
189 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500190 const std::string& chassisId, const std::string& powerSupplyId,
191 std::function<void(const std::string& powerSupplyPath,
192 const std::string& service)>&& callback)
George Liu00ef5dc2022-10-05 16:27:52 +0800193{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500194 const std::string reqpath = "/xyz/openbmc_project/inventory";
195
196 dbus::utility::getAssociatedSubTreeById(
Myung Bae3f95a272024-03-13 07:32:02 -0700197 chassisId, reqpath, chassisInterfaces, "powered_by",
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -0500198 powerSupplyInterface,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500199 [asyncResp, chassisId, powerSupplyId, callback{std::move(callback)}](
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -0500200 const boost::system::error_code& ec,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500201 const dbus::utility::MapperGetSubTreeResponse& subtree) {
202 afterGetValidPowerSupplyPath(asyncResp, powerSupplyId, ec, subtree,
203 callback);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400204 });
George Liu00ef5dc2022-10-05 16:27:52 +0800205}
206
Patrick Williams504af5a2025-02-03 14:29:03 -0500207inline void getPowerSupplyState(
208 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
209 const std::string& service, const std::string& path)
George Liu34dfcb92022-10-05 16:47:44 +0800210{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800211 dbus::utility::getProperty<bool>(
212 service, path, "xyz.openbmc_project.Inventory.Item", "Present",
George Liu34dfcb92022-10-05 16:47:44 +0800213 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400214 if (ec)
George Liu34dfcb92022-10-05 16:47:44 +0800215 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400216 if (ec.value() != EBADR)
217 {
218 BMCWEB_LOG_ERROR("DBUS response error for State {}",
219 ec.value());
220 messages::internalError(asyncResp->res);
221 }
222 return;
George Liu34dfcb92022-10-05 16:47:44 +0800223 }
George Liu34dfcb92022-10-05 16:47:44 +0800224
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400225 if (!value)
226 {
227 asyncResp->res.jsonValue["Status"]["State"] =
228 resource::State::Absent;
229 }
230 });
George Liu34dfcb92022-10-05 16:47:44 +0800231}
232
Patrick Williams504af5a2025-02-03 14:29:03 -0500233inline void getPowerSupplyHealth(
234 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
235 const std::string& service, const std::string& path)
George Liu34dfcb92022-10-05 16:47:44 +0800236{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800237 dbus::utility::getProperty<bool>(
238 service, path, "xyz.openbmc_project.State.Decorator.OperationalStatus",
239 "Functional",
George Liu34dfcb92022-10-05 16:47:44 +0800240 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400241 if (ec)
George Liu34dfcb92022-10-05 16:47:44 +0800242 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400243 if (ec.value() != EBADR)
244 {
245 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
246 ec.value());
247 messages::internalError(asyncResp->res);
248 }
249 return;
George Liu34dfcb92022-10-05 16:47:44 +0800250 }
George Liu34dfcb92022-10-05 16:47:44 +0800251
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400252 if (!value)
253 {
254 asyncResp->res.jsonValue["Status"]["Health"] =
255 resource::Health::Critical;
256 }
257 });
George Liu34dfcb92022-10-05 16:47:44 +0800258}
259
Patrick Williams504af5a2025-02-03 14:29:03 -0500260inline void getPowerSupplyAsset(
261 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
262 const std::string& service, const std::string& path)
George Liu2b45fb32022-10-05 17:00:00 +0800263{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800264 dbus::utility::getAllProperties(
265 service, path, "xyz.openbmc_project.Inventory.Decorator.Asset",
George Liu2b45fb32022-10-05 17:00:00 +0800266 [asyncResp](const boost::system::error_code& ec,
267 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400268 if (ec)
George Liu2b45fb32022-10-05 17:00:00 +0800269 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400270 if (ec.value() != EBADR)
271 {
272 BMCWEB_LOG_ERROR("DBUS response error for Asset {}",
273 ec.value());
274 messages::internalError(asyncResp->res);
275 }
276 return;
George Liu2b45fb32022-10-05 17:00:00 +0800277 }
George Liu2b45fb32022-10-05 17:00:00 +0800278
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400279 const std::string* partNumber = nullptr;
280 const std::string* serialNumber = nullptr;
281 const std::string* manufacturer = nullptr;
282 const std::string* model = nullptr;
283 const std::string* sparePartNumber = nullptr;
Hieu Huynhb5190062024-07-11 03:47:21 +0000284 const std::string* buildDate = nullptr;
George Liu2b45fb32022-10-05 17:00:00 +0800285
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400286 const bool success = sdbusplus::unpackPropertiesNoThrow(
287 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
288 partNumber, "SerialNumber", serialNumber, "Manufacturer",
289 manufacturer, "Model", model, "SparePartNumber",
Hieu Huynhb5190062024-07-11 03:47:21 +0000290 sparePartNumber, "BuildDate", buildDate);
George Liu2b45fb32022-10-05 17:00:00 +0800291
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400292 if (!success)
293 {
294 messages::internalError(asyncResp->res);
295 return;
296 }
George Liu2b45fb32022-10-05 17:00:00 +0800297
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400298 if (partNumber != nullptr)
299 {
300 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
301 }
George Liu2b45fb32022-10-05 17:00:00 +0800302
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400303 if (serialNumber != nullptr)
304 {
305 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
306 }
George Liu2b45fb32022-10-05 17:00:00 +0800307
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400308 if (manufacturer != nullptr)
309 {
310 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
311 }
George Liu2b45fb32022-10-05 17:00:00 +0800312
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400313 if (model != nullptr)
314 {
315 asyncResp->res.jsonValue["Model"] = *model;
316 }
George Liu2b45fb32022-10-05 17:00:00 +0800317
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400318 // SparePartNumber is optional on D-Bus so skip if it is empty
319 if (sparePartNumber != nullptr && !sparePartNumber->empty())
320 {
321 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
322 }
Hieu Huynhb5190062024-07-11 03:47:21 +0000323
324 if (buildDate != nullptr)
325 {
326 time_utils::productionDateReport(asyncResp->res, *buildDate);
327 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400328 });
George Liu2b45fb32022-10-05 17:00:00 +0800329}
330
George Liua0dba872022-10-05 17:03:20 +0800331inline void getPowerSupplyFirmwareVersion(
332 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
333 const std::string& service, const std::string& path)
334{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800335 dbus::utility::getProperty<std::string>(
336 service, path, "xyz.openbmc_project.Software.Version", "Version",
George Liua0dba872022-10-05 17:03:20 +0800337 [asyncResp](const boost::system::error_code& ec,
338 const std::string& value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400339 if (ec)
George Liua0dba872022-10-05 17:03:20 +0800340 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400341 if (ec.value() != EBADR)
342 {
343 BMCWEB_LOG_ERROR(
344 "DBUS response error for FirmwareVersion {}",
345 ec.value());
346 messages::internalError(asyncResp->res);
347 }
348 return;
George Liua0dba872022-10-05 17:03:20 +0800349 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400350 asyncResp->res.jsonValue["FirmwareVersion"] = value;
351 });
George Liua0dba872022-10-05 17:03:20 +0800352}
353
Patrick Williams504af5a2025-02-03 14:29:03 -0500354inline void getPowerSupplyLocation(
355 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
356 const std::string& service, const std::string& path)
George Liu44845e52022-10-05 17:09:21 +0800357{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800358 dbus::utility::getProperty<std::string>(
359 service, path, "xyz.openbmc_project.Inventory.Decorator.LocationCode",
360 "LocationCode",
George Liu44845e52022-10-05 17:09:21 +0800361 [asyncResp](const boost::system::error_code& ec,
362 const std::string& value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400363 if (ec)
George Liu44845e52022-10-05 17:09:21 +0800364 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400365 if (ec.value() != EBADR)
366 {
367 BMCWEB_LOG_ERROR("DBUS response error for Location {}",
368 ec.value());
369 messages::internalError(asyncResp->res);
370 }
371 return;
George Liu44845e52022-10-05 17:09:21 +0800372 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400373 asyncResp->res
374 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = value;
375 });
George Liu44845e52022-10-05 17:09:21 +0800376}
377
George Liuddceee02022-10-06 08:57:11 +0800378inline void handleGetEfficiencyResponse(
379 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
380 const boost::system::error_code& ec, uint32_t value)
381{
382 if (ec)
383 {
384 if (ec.value() != EBADR)
385 {
Ed Tanous62598e32023-07-17 17:06:25 -0700386 BMCWEB_LOG_ERROR("DBUS response error for DeratingFactor {}",
387 ec.value());
George Liuddceee02022-10-06 08:57:11 +0800388 messages::internalError(asyncResp->res);
389 }
390 return;
391 }
392 // The PDI default value is 0, if it hasn't been set leave off
393 if (value == 0)
394 {
395 return;
396 }
397
398 nlohmann::json::array_t efficiencyRatings;
399 nlohmann::json::object_t efficiencyPercent;
400 efficiencyPercent["EfficiencyPercent"] = value;
401 efficiencyRatings.emplace_back(std::move(efficiencyPercent));
402 asyncResp->res.jsonValue["EfficiencyRatings"] =
403 std::move(efficiencyRatings);
404}
405
406inline void handlePowerSupplyAttributesSubTreeResponse(
407 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
408 const boost::system::error_code& ec,
409 const dbus::utility::MapperGetSubTreeResponse& subtree)
410{
411 if (ec)
412 {
413 if (ec.value() != EBADR)
414 {
Ed Tanous62598e32023-07-17 17:06:25 -0700415 BMCWEB_LOG_ERROR("DBUS response error for EfficiencyPercent {}",
416 ec.value());
George Liuddceee02022-10-06 08:57:11 +0800417 messages::internalError(asyncResp->res);
418 }
419 return;
420 }
421
422 if (subtree.empty())
423 {
Ed Tanous62598e32023-07-17 17:06:25 -0700424 BMCWEB_LOG_DEBUG("Can't find Power Supply Attributes!");
George Liuddceee02022-10-06 08:57:11 +0800425 return;
426 }
427
428 if (subtree.size() != 1)
429 {
Ed Tanous62598e32023-07-17 17:06:25 -0700430 BMCWEB_LOG_ERROR(
431 "Unexpected number of paths returned by getSubTree: {}",
432 subtree.size());
George Liuddceee02022-10-06 08:57:11 +0800433 messages::internalError(asyncResp->res);
434 return;
435 }
436
437 const auto& [path, serviceMap] = *subtree.begin();
438 const auto& [service, interfaces] = *serviceMap.begin();
Ed Tanousdeae6a72024-11-11 21:58:57 -0800439 dbus::utility::getProperty<uint32_t>(
440 service, path, "xyz.openbmc_project.Control.PowerSupplyAttributes",
441 "DeratingFactor",
George Liuddceee02022-10-06 08:57:11 +0800442 [asyncResp](const boost::system::error_code& ec1, uint32_t value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400443 handleGetEfficiencyResponse(asyncResp, ec1, value);
444 });
George Liuddceee02022-10-06 08:57:11 +0800445}
446
Patrick Williams504af5a2025-02-03 14:29:03 -0500447inline void getEfficiencyPercent(
448 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuddceee02022-10-06 08:57:11 +0800449{
450 constexpr std::array<std::string_view, 1> efficiencyIntf = {
451 "xyz.openbmc_project.Control.PowerSupplyAttributes"};
452
453 dbus::utility::getSubTree(
454 "/xyz/openbmc_project", 0, efficiencyIntf,
455 [asyncResp](const boost::system::error_code& ec,
456 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400457 handlePowerSupplyAttributesSubTreeResponse(asyncResp, ec, subtree);
458 });
George Liuddceee02022-10-06 08:57:11 +0800459}
460
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400461inline void doPowerSupplyGet(
462 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
463 const std::string& chassisId, const std::string& powerSupplyId,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500464 const std::string& powerSupplyPath, const std::string& service)
George Liu00ef5dc2022-10-05 16:27:52 +0800465{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500466 asyncResp->res.addHeader(
467 boost::beast::http::field::link,
468 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
469 asyncResp->res.jsonValue["@odata.type"] = "#PowerSupply.v1_5_0.PowerSupply";
470 asyncResp->res.jsonValue["Name"] = "Power Supply";
471 asyncResp->res.jsonValue["Id"] = powerSupplyId;
472 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
473 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
474 powerSupplyId);
George Liu00ef5dc2022-10-05 16:27:52 +0800475
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500476 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
477 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
George Liu34dfcb92022-10-05 16:47:44 +0800478
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500479 getPowerSupplyState(asyncResp, service, powerSupplyPath);
480 getPowerSupplyHealth(asyncResp, service, powerSupplyPath);
481 getPowerSupplyAsset(asyncResp, service, powerSupplyPath);
482 getPowerSupplyFirmwareVersion(asyncResp, service, powerSupplyPath);
483 getPowerSupplyLocation(asyncResp, service, powerSupplyPath);
484 getEfficiencyPercent(asyncResp);
George Liu00ef5dc2022-10-05 16:27:52 +0800485}
486
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400487inline void handlePowerSupplyHead(
488 App& app, const crow::Request& req,
489 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
490 const std::string& chassisId, const std::string& powerSupplyId)
George Liu00ef5dc2022-10-05 16:27:52 +0800491{
492 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
493 {
494 return;
495 }
496
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500497 // Get the correct Path and Service that match the input parameters
498 getValidPowerSupplyPath(
499 asyncResp, chassisId, powerSupplyId,
500 [asyncResp](const std::string&, const std::string&) {
501 asyncResp->res.addHeader(
502 boost::beast::http::field::link,
503 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
George Liu00ef5dc2022-10-05 16:27:52 +0800504 });
George Liu00ef5dc2022-10-05 16:27:52 +0800505}
506
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400507inline void handlePowerSupplyGet(
508 App& app, const crow::Request& req,
509 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
510 const std::string& chassisId, const std::string& powerSupplyId)
George Liu00ef5dc2022-10-05 16:27:52 +0800511{
512 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
513 {
514 return;
515 }
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500516 getValidPowerSupplyPath(
517 asyncResp, chassisId, powerSupplyId,
George Liu00ef5dc2022-10-05 16:27:52 +0800518 std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId));
519}
520
521inline void requestRoutesPowerSupply(App& app)
522{
523 BMCWEB_ROUTE(
524 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
525 .privileges(redfish::privileges::headPowerSupply)
526 .methods(boost::beast::http::verb::head)(
527 std::bind_front(handlePowerSupplyHead, std::ref(app)));
528
529 BMCWEB_ROUTE(
530 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
531 .privileges(redfish::privileges::getPowerSupply)
532 .methods(boost::beast::http::verb::get)(
533 std::bind_front(handlePowerSupplyGet, std::ref(app)));
534}
535
George Liua7210022022-10-05 15:44:11 +0800536} // namespace redfish