blob: 9d2d3ce51a83dc34cb4f33344961d6239fc72025 [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 constexpr std::array<std::string_view, 2> chasisInterfaces = {
134 "xyz.openbmc_project.Inventory.Item.Board",
135 "xyz.openbmc_project.Inventory.Item.Chassis"};
136 const std::string reqpath = "/xyz/openbmc_project/inventory";
137
138 dbus::utility::getAssociatedSubTreePathsById(
139 chassisId, reqpath, chasisInterfaces, "powered_by",
140 powerSupplyInterface,
141 [asyncResp, chassisId](
142 const boost::system::error_code& ec,
143 const dbus::utility::MapperGetSubTreePathsResponse& subtreePaths) {
144 doPowerSupplyCollection(asyncResp, chassisId, ec, subtreePaths);
145 });
George Liua7210022022-10-05 15:44:11 +0800146}
147
148inline void requestRoutesPowerSupplyCollection(App& app)
149{
150 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
151 .privileges(redfish::privileges::headPowerSupplyCollection)
152 .methods(boost::beast::http::verb::head)(
153 std::bind_front(handlePowerSupplyCollectionHead, std::ref(app)));
154
155 BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/")
156 .privileges(redfish::privileges::getPowerSupplyCollection)
157 .methods(boost::beast::http::verb::get)(
158 std::bind_front(handlePowerSupplyCollectionGet, std::ref(app)));
159}
160
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500161inline void afterGetValidPowerSupplyPath(
162 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
163 const std::string& powerSupplyId, const boost::system::error_code& ec,
164 const dbus::utility::MapperGetSubTreeResponse& subtree,
165 const std::function<void(const std::string& powerSupplyPath,
166 const std::string& service)>& callback)
George Liu00ef5dc2022-10-05 16:27:52 +0800167{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500168 if (ec)
169 {
170 if (ec.value() != EBADR)
171 {
172 BMCWEB_LOG_ERROR("DBUS response error{}", ec.value());
173 messages::internalError(asyncResp->res);
174 }
175 return;
176 }
177 for (const auto& [objectPath, service] : subtree)
178 {
179 sdbusplus::message::object_path path(objectPath);
Myung Baed8e2b612024-10-08 12:19:19 -0500180 if (path.filename() == powerSupplyId)
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500181 {
182 callback(path, service.begin()->first);
183 return;
184 }
185 }
George Liu00ef5dc2022-10-05 16:27:52 +0800186
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500187 BMCWEB_LOG_WARNING("Power supply not found: {}", powerSupplyId);
188 messages::resourceNotFound(asyncResp->res, "PowerSupplies", powerSupplyId);
George Liu00ef5dc2022-10-05 16:27:52 +0800189}
190
George Liu34dfcb92022-10-05 16:47:44 +0800191inline void getValidPowerSupplyPath(
192 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500193 const std::string& chassisId, const std::string& powerSupplyId,
194 std::function<void(const std::string& powerSupplyPath,
195 const std::string& service)>&& callback)
George Liu00ef5dc2022-10-05 16:27:52 +0800196{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500197 constexpr std::array<std::string_view, 2> chasisInterfaces = {
198 "xyz.openbmc_project.Inventory.Item.Board",
199 "xyz.openbmc_project.Inventory.Item.Chassis"};
200 const std::string reqpath = "/xyz/openbmc_project/inventory";
201
202 dbus::utility::getAssociatedSubTreeById(
203 chassisId, reqpath, chasisInterfaces, "powered_by",
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -0500204 powerSupplyInterface,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500205 [asyncResp, chassisId, powerSupplyId, callback{std::move(callback)}](
Lakshmi Yadlapati788fe6c2023-06-21 14:39:08 -0500206 const boost::system::error_code& ec,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500207 const dbus::utility::MapperGetSubTreeResponse& subtree) {
208 afterGetValidPowerSupplyPath(asyncResp, powerSupplyId, ec, subtree,
209 callback);
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400210 });
George Liu00ef5dc2022-10-05 16:27:52 +0800211}
212
Patrick Williams504af5a2025-02-03 14:29:03 -0500213inline void getPowerSupplyState(
214 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
215 const std::string& service, const std::string& path)
George Liu34dfcb92022-10-05 16:47:44 +0800216{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800217 dbus::utility::getProperty<bool>(
218 service, path, "xyz.openbmc_project.Inventory.Item", "Present",
George Liu34dfcb92022-10-05 16:47:44 +0800219 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400220 if (ec)
George Liu34dfcb92022-10-05 16:47:44 +0800221 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400222 if (ec.value() != EBADR)
223 {
224 BMCWEB_LOG_ERROR("DBUS response error for State {}",
225 ec.value());
226 messages::internalError(asyncResp->res);
227 }
228 return;
George Liu34dfcb92022-10-05 16:47:44 +0800229 }
George Liu34dfcb92022-10-05 16:47:44 +0800230
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400231 if (!value)
232 {
233 asyncResp->res.jsonValue["Status"]["State"] =
234 resource::State::Absent;
235 }
236 });
George Liu34dfcb92022-10-05 16:47:44 +0800237}
238
Patrick Williams504af5a2025-02-03 14:29:03 -0500239inline void getPowerSupplyHealth(
240 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
241 const std::string& service, const std::string& path)
George Liu34dfcb92022-10-05 16:47:44 +0800242{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800243 dbus::utility::getProperty<bool>(
244 service, path, "xyz.openbmc_project.State.Decorator.OperationalStatus",
245 "Functional",
George Liu34dfcb92022-10-05 16:47:44 +0800246 [asyncResp](const boost::system::error_code& ec, const bool value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400247 if (ec)
George Liu34dfcb92022-10-05 16:47:44 +0800248 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400249 if (ec.value() != EBADR)
250 {
251 BMCWEB_LOG_ERROR("DBUS response error for Health {}",
252 ec.value());
253 messages::internalError(asyncResp->res);
254 }
255 return;
George Liu34dfcb92022-10-05 16:47:44 +0800256 }
George Liu34dfcb92022-10-05 16:47:44 +0800257
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400258 if (!value)
259 {
260 asyncResp->res.jsonValue["Status"]["Health"] =
261 resource::Health::Critical;
262 }
263 });
George Liu34dfcb92022-10-05 16:47:44 +0800264}
265
Patrick Williams504af5a2025-02-03 14:29:03 -0500266inline void getPowerSupplyAsset(
267 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
268 const std::string& service, const std::string& path)
George Liu2b45fb32022-10-05 17:00:00 +0800269{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800270 dbus::utility::getAllProperties(
271 service, path, "xyz.openbmc_project.Inventory.Decorator.Asset",
George Liu2b45fb32022-10-05 17:00:00 +0800272 [asyncResp](const boost::system::error_code& ec,
273 const dbus::utility::DBusPropertiesMap& propertiesList) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400274 if (ec)
George Liu2b45fb32022-10-05 17:00:00 +0800275 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400276 if (ec.value() != EBADR)
277 {
278 BMCWEB_LOG_ERROR("DBUS response error for Asset {}",
279 ec.value());
280 messages::internalError(asyncResp->res);
281 }
282 return;
George Liu2b45fb32022-10-05 17:00:00 +0800283 }
George Liu2b45fb32022-10-05 17:00:00 +0800284
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400285 const std::string* partNumber = nullptr;
286 const std::string* serialNumber = nullptr;
287 const std::string* manufacturer = nullptr;
288 const std::string* model = nullptr;
289 const std::string* sparePartNumber = nullptr;
Hieu Huynhb5190062024-07-11 03:47:21 +0000290 const std::string* buildDate = nullptr;
George Liu2b45fb32022-10-05 17:00:00 +0800291
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400292 const bool success = sdbusplus::unpackPropertiesNoThrow(
293 dbus_utils::UnpackErrorPrinter(), propertiesList, "PartNumber",
294 partNumber, "SerialNumber", serialNumber, "Manufacturer",
295 manufacturer, "Model", model, "SparePartNumber",
Hieu Huynhb5190062024-07-11 03:47:21 +0000296 sparePartNumber, "BuildDate", buildDate);
George Liu2b45fb32022-10-05 17:00:00 +0800297
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400298 if (!success)
299 {
300 messages::internalError(asyncResp->res);
301 return;
302 }
George Liu2b45fb32022-10-05 17:00:00 +0800303
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400304 if (partNumber != nullptr)
305 {
306 asyncResp->res.jsonValue["PartNumber"] = *partNumber;
307 }
George Liu2b45fb32022-10-05 17:00:00 +0800308
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400309 if (serialNumber != nullptr)
310 {
311 asyncResp->res.jsonValue["SerialNumber"] = *serialNumber;
312 }
George Liu2b45fb32022-10-05 17:00:00 +0800313
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400314 if (manufacturer != nullptr)
315 {
316 asyncResp->res.jsonValue["Manufacturer"] = *manufacturer;
317 }
George Liu2b45fb32022-10-05 17:00:00 +0800318
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400319 if (model != nullptr)
320 {
321 asyncResp->res.jsonValue["Model"] = *model;
322 }
George Liu2b45fb32022-10-05 17:00:00 +0800323
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400324 // SparePartNumber is optional on D-Bus so skip if it is empty
325 if (sparePartNumber != nullptr && !sparePartNumber->empty())
326 {
327 asyncResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
328 }
Hieu Huynhb5190062024-07-11 03:47:21 +0000329
330 if (buildDate != nullptr)
331 {
332 time_utils::productionDateReport(asyncResp->res, *buildDate);
333 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400334 });
George Liu2b45fb32022-10-05 17:00:00 +0800335}
336
George Liua0dba872022-10-05 17:03:20 +0800337inline void getPowerSupplyFirmwareVersion(
338 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
339 const std::string& service, const std::string& path)
340{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800341 dbus::utility::getProperty<std::string>(
342 service, path, "xyz.openbmc_project.Software.Version", "Version",
George Liua0dba872022-10-05 17:03:20 +0800343 [asyncResp](const boost::system::error_code& ec,
344 const std::string& value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400345 if (ec)
George Liua0dba872022-10-05 17:03:20 +0800346 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400347 if (ec.value() != EBADR)
348 {
349 BMCWEB_LOG_ERROR(
350 "DBUS response error for FirmwareVersion {}",
351 ec.value());
352 messages::internalError(asyncResp->res);
353 }
354 return;
George Liua0dba872022-10-05 17:03:20 +0800355 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400356 asyncResp->res.jsonValue["FirmwareVersion"] = value;
357 });
George Liua0dba872022-10-05 17:03:20 +0800358}
359
Patrick Williams504af5a2025-02-03 14:29:03 -0500360inline void getPowerSupplyLocation(
361 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
362 const std::string& service, const std::string& path)
George Liu44845e52022-10-05 17:09:21 +0800363{
Ed Tanousdeae6a72024-11-11 21:58:57 -0800364 dbus::utility::getProperty<std::string>(
365 service, path, "xyz.openbmc_project.Inventory.Decorator.LocationCode",
366 "LocationCode",
George Liu44845e52022-10-05 17:09:21 +0800367 [asyncResp](const boost::system::error_code& ec,
368 const std::string& value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400369 if (ec)
George Liu44845e52022-10-05 17:09:21 +0800370 {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400371 if (ec.value() != EBADR)
372 {
373 BMCWEB_LOG_ERROR("DBUS response error for Location {}",
374 ec.value());
375 messages::internalError(asyncResp->res);
376 }
377 return;
George Liu44845e52022-10-05 17:09:21 +0800378 }
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400379 asyncResp->res
380 .jsonValue["Location"]["PartLocation"]["ServiceLabel"] = value;
381 });
George Liu44845e52022-10-05 17:09:21 +0800382}
383
George Liuddceee02022-10-06 08:57:11 +0800384inline void handleGetEfficiencyResponse(
385 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
386 const boost::system::error_code& ec, uint32_t value)
387{
388 if (ec)
389 {
390 if (ec.value() != EBADR)
391 {
Ed Tanous62598e32023-07-17 17:06:25 -0700392 BMCWEB_LOG_ERROR("DBUS response error for DeratingFactor {}",
393 ec.value());
George Liuddceee02022-10-06 08:57:11 +0800394 messages::internalError(asyncResp->res);
395 }
396 return;
397 }
398 // The PDI default value is 0, if it hasn't been set leave off
399 if (value == 0)
400 {
401 return;
402 }
403
404 nlohmann::json::array_t efficiencyRatings;
405 nlohmann::json::object_t efficiencyPercent;
406 efficiencyPercent["EfficiencyPercent"] = value;
407 efficiencyRatings.emplace_back(std::move(efficiencyPercent));
408 asyncResp->res.jsonValue["EfficiencyRatings"] =
409 std::move(efficiencyRatings);
410}
411
412inline void handlePowerSupplyAttributesSubTreeResponse(
413 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
414 const boost::system::error_code& ec,
415 const dbus::utility::MapperGetSubTreeResponse& subtree)
416{
417 if (ec)
418 {
419 if (ec.value() != EBADR)
420 {
Ed Tanous62598e32023-07-17 17:06:25 -0700421 BMCWEB_LOG_ERROR("DBUS response error for EfficiencyPercent {}",
422 ec.value());
George Liuddceee02022-10-06 08:57:11 +0800423 messages::internalError(asyncResp->res);
424 }
425 return;
426 }
427
428 if (subtree.empty())
429 {
Ed Tanous62598e32023-07-17 17:06:25 -0700430 BMCWEB_LOG_DEBUG("Can't find Power Supply Attributes!");
George Liuddceee02022-10-06 08:57:11 +0800431 return;
432 }
433
434 if (subtree.size() != 1)
435 {
Ed Tanous62598e32023-07-17 17:06:25 -0700436 BMCWEB_LOG_ERROR(
437 "Unexpected number of paths returned by getSubTree: {}",
438 subtree.size());
George Liuddceee02022-10-06 08:57:11 +0800439 messages::internalError(asyncResp->res);
440 return;
441 }
442
443 const auto& [path, serviceMap] = *subtree.begin();
444 const auto& [service, interfaces] = *serviceMap.begin();
Ed Tanousdeae6a72024-11-11 21:58:57 -0800445 dbus::utility::getProperty<uint32_t>(
446 service, path, "xyz.openbmc_project.Control.PowerSupplyAttributes",
447 "DeratingFactor",
George Liuddceee02022-10-06 08:57:11 +0800448 [asyncResp](const boost::system::error_code& ec1, uint32_t value) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400449 handleGetEfficiencyResponse(asyncResp, ec1, value);
450 });
George Liuddceee02022-10-06 08:57:11 +0800451}
452
Patrick Williams504af5a2025-02-03 14:29:03 -0500453inline void getEfficiencyPercent(
454 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
George Liuddceee02022-10-06 08:57:11 +0800455{
456 constexpr std::array<std::string_view, 1> efficiencyIntf = {
457 "xyz.openbmc_project.Control.PowerSupplyAttributes"};
458
459 dbus::utility::getSubTree(
460 "/xyz/openbmc_project", 0, efficiencyIntf,
461 [asyncResp](const boost::system::error_code& ec,
462 const dbus::utility::MapperGetSubTreeResponse& subtree) {
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400463 handlePowerSupplyAttributesSubTreeResponse(asyncResp, ec, subtree);
464 });
George Liuddceee02022-10-06 08:57:11 +0800465}
466
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400467inline void doPowerSupplyGet(
468 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
469 const std::string& chassisId, const std::string& powerSupplyId,
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500470 const std::string& powerSupplyPath, const std::string& service)
George Liu00ef5dc2022-10-05 16:27:52 +0800471{
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500472 asyncResp->res.addHeader(
473 boost::beast::http::field::link,
474 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
475 asyncResp->res.jsonValue["@odata.type"] = "#PowerSupply.v1_5_0.PowerSupply";
476 asyncResp->res.jsonValue["Name"] = "Power Supply";
477 asyncResp->res.jsonValue["Id"] = powerSupplyId;
478 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format(
479 "/redfish/v1/Chassis/{}/PowerSubsystem/PowerSupplies/{}", chassisId,
480 powerSupplyId);
George Liu00ef5dc2022-10-05 16:27:52 +0800481
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500482 asyncResp->res.jsonValue["Status"]["State"] = resource::State::Enabled;
483 asyncResp->res.jsonValue["Status"]["Health"] = resource::Health::OK;
George Liu34dfcb92022-10-05 16:47:44 +0800484
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500485 getPowerSupplyState(asyncResp, service, powerSupplyPath);
486 getPowerSupplyHealth(asyncResp, service, powerSupplyPath);
487 getPowerSupplyAsset(asyncResp, service, powerSupplyPath);
488 getPowerSupplyFirmwareVersion(asyncResp, service, powerSupplyPath);
489 getPowerSupplyLocation(asyncResp, service, powerSupplyPath);
490 getEfficiencyPercent(asyncResp);
George Liu00ef5dc2022-10-05 16:27:52 +0800491}
492
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400493inline void handlePowerSupplyHead(
494 App& app, const crow::Request& req,
495 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
496 const std::string& chassisId, const std::string& powerSupplyId)
George Liu00ef5dc2022-10-05 16:27:52 +0800497{
498 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
499 {
500 return;
501 }
502
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500503 // Get the correct Path and Service that match the input parameters
504 getValidPowerSupplyPath(
505 asyncResp, chassisId, powerSupplyId,
506 [asyncResp](const std::string&, const std::string&) {
507 asyncResp->res.addHeader(
508 boost::beast::http::field::link,
509 "</redfish/v1/JsonSchemas/PowerSupply/PowerSupply.json>; rel=describedby");
George Liu00ef5dc2022-10-05 16:27:52 +0800510 });
George Liu00ef5dc2022-10-05 16:27:52 +0800511}
512
Patrick Williamsbd79bce2024-08-16 15:22:20 -0400513inline void handlePowerSupplyGet(
514 App& app, const crow::Request& req,
515 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
516 const std::string& chassisId, const std::string& powerSupplyId)
George Liu00ef5dc2022-10-05 16:27:52 +0800517{
518 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
519 {
520 return;
521 }
Lakshmi Yadlapati3e42a322024-06-26 18:28:06 -0500522 getValidPowerSupplyPath(
523 asyncResp, chassisId, powerSupplyId,
George Liu00ef5dc2022-10-05 16:27:52 +0800524 std::bind_front(doPowerSupplyGet, asyncResp, chassisId, powerSupplyId));
525}
526
527inline void requestRoutesPowerSupply(App& app)
528{
529 BMCWEB_ROUTE(
530 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
531 .privileges(redfish::privileges::headPowerSupply)
532 .methods(boost::beast::http::verb::head)(
533 std::bind_front(handlePowerSupplyHead, std::ref(app)));
534
535 BMCWEB_ROUTE(
536 app, "/redfish/v1/Chassis/<str>/PowerSubsystem/PowerSupplies/<str>/")
537 .privileges(redfish::privileges::getPowerSupply)
538 .methods(boost::beast::http::verb::get)(
539 std::bind_front(handlePowerSupplyGet, std::ref(app)));
540}
541
George Liua7210022022-10-05 15:44:11 +0800542} // namespace redfish