15ae1f7f3Szhanghch05 #pragma once 25ae1f7f3Szhanghch05 35ae1f7f3Szhanghch05 #include "app.hpp" 46fe8751cSGeorge Liu #include "dbus_utility.hpp" 55ae1f7f3Szhanghch05 #include "query.hpp" 65ae1f7f3Szhanghch05 #include "registries/privilege_registry.hpp" 75ae1f7f3Szhanghch05 #include "utils/chassis_utils.hpp" 86fe8751cSGeorge Liu #include "utils/json_utils.hpp" 96fe8751cSGeorge Liu #include "utils/sensor_utils.hpp" 105ae1f7f3Szhanghch05 116fe8751cSGeorge Liu #include <boost/system/error_code.hpp> 126fe8751cSGeorge Liu 136fe8751cSGeorge Liu #include <array> 145ae1f7f3Szhanghch05 #include <functional> 155ae1f7f3Szhanghch05 #include <memory> 165ae1f7f3Szhanghch05 #include <optional> 175ae1f7f3Szhanghch05 #include <string> 186fe8751cSGeorge Liu #include <string_view> 195ae1f7f3Szhanghch05 205ae1f7f3Szhanghch05 namespace redfish 215ae1f7f3Szhanghch05 { 226fe8751cSGeorge Liu inline void afterGetTemperatureValue( 236fe8751cSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 246fe8751cSGeorge Liu const std::string& chassisId, const std::string& path, 256fe8751cSGeorge Liu const boost::system::error_code& ec, 266fe8751cSGeorge Liu const dbus::utility::DBusPropertiesMap& valuesDict) 276fe8751cSGeorge Liu { 286fe8751cSGeorge Liu if (ec) 296fe8751cSGeorge Liu { 306fe8751cSGeorge Liu if (ec.value() != EBADR) 316fe8751cSGeorge Liu { 326fe8751cSGeorge Liu BMCWEB_LOG_ERROR("DBUS response error for getAllProperties {}", 336fe8751cSGeorge Liu ec.value()); 346fe8751cSGeorge Liu messages::internalError(asyncResp->res); 356fe8751cSGeorge Liu } 366fe8751cSGeorge Liu return; 376fe8751cSGeorge Liu } 386fe8751cSGeorge Liu 396fe8751cSGeorge Liu nlohmann::json item = nlohmann::json::object(); 406fe8751cSGeorge Liu 416fe8751cSGeorge Liu /* Don't return an error for a failure to fill in properties from any of 426fe8751cSGeorge Liu * the sensors in the list. Just skip it. 436fe8751cSGeorge Liu */ 446fe8751cSGeorge Liu if (sensor_utils::objectExcerptToJson( 456fe8751cSGeorge Liu path, chassisId, sensor_utils::ChassisSubNode::thermalMetricsNode, 466fe8751cSGeorge Liu "temperature", valuesDict, item)) 476fe8751cSGeorge Liu { 486fe8751cSGeorge Liu nlohmann::json& temperatureReadings = 496fe8751cSGeorge Liu asyncResp->res.jsonValue["TemperatureReadingsCelsius"]; 506fe8751cSGeorge Liu nlohmann::json::array_t* temperatureArray = 516fe8751cSGeorge Liu temperatureReadings.get_ptr<nlohmann::json::array_t*>(); 526fe8751cSGeorge Liu if (temperatureArray == nullptr) 536fe8751cSGeorge Liu { 546fe8751cSGeorge Liu BMCWEB_LOG_ERROR("Missing TemperatureReadingsCelsius Json array"); 556fe8751cSGeorge Liu messages::internalError(asyncResp->res); 566fe8751cSGeorge Liu return; 576fe8751cSGeorge Liu } 586fe8751cSGeorge Liu 596fe8751cSGeorge Liu temperatureArray->emplace_back(std::move(item)); 606fe8751cSGeorge Liu asyncResp->res.jsonValue["TemperatureReadingsCelsius@odata.count"] = 616fe8751cSGeorge Liu temperatureArray->size(); 626fe8751cSGeorge Liu 636fe8751cSGeorge Liu json_util::sortJsonArrayByKey(*temperatureArray, "DataSourceUri"); 646fe8751cSGeorge Liu } 656fe8751cSGeorge Liu } 666fe8751cSGeorge Liu 676fe8751cSGeorge Liu inline void handleTemperatureReadingsCelsius( 686fe8751cSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 696fe8751cSGeorge Liu const std::string& chassisId, const boost::system::error_code& ec, 706fe8751cSGeorge Liu const sensor_utils::SensorServicePathList& sensorsServiceAndPath) 716fe8751cSGeorge Liu { 726fe8751cSGeorge Liu if (ec) 736fe8751cSGeorge Liu { 746fe8751cSGeorge Liu if (ec.value() != EBADR) 756fe8751cSGeorge Liu { 766fe8751cSGeorge Liu BMCWEB_LOG_ERROR("DBUS response error for getAssociatedSubTree {}", 776fe8751cSGeorge Liu ec.value()); 786fe8751cSGeorge Liu messages::internalError(asyncResp->res); 796fe8751cSGeorge Liu } 806fe8751cSGeorge Liu return; 816fe8751cSGeorge Liu } 826fe8751cSGeorge Liu 836fe8751cSGeorge Liu asyncResp->res.jsonValue["TemperatureReadingsCelsius"] = 846fe8751cSGeorge Liu nlohmann::json::array_t(); 856fe8751cSGeorge Liu asyncResp->res.jsonValue["TemperatureReadingsCelsius@odata.count"] = 0; 866fe8751cSGeorge Liu 876fe8751cSGeorge Liu for (const auto& [service, sensorPath] : sensorsServiceAndPath) 886fe8751cSGeorge Liu { 89*deae6a78SEd Tanous dbus::utility::getAllProperties( 906fe8751cSGeorge Liu *crow::connections::systemBus, service, sensorPath, 916fe8751cSGeorge Liu "xyz.openbmc_project.Sensor.Value", 926fe8751cSGeorge Liu [asyncResp, chassisId, 936fe8751cSGeorge Liu sensorPath](const boost::system::error_code& ec1, 946fe8751cSGeorge Liu const dbus::utility::DBusPropertiesMap& properties) { 956fe8751cSGeorge Liu afterGetTemperatureValue(asyncResp, chassisId, sensorPath, ec1, 966fe8751cSGeorge Liu properties); 976fe8751cSGeorge Liu }); 986fe8751cSGeorge Liu } 996fe8751cSGeorge Liu } 1006fe8751cSGeorge Liu 1016fe8751cSGeorge Liu inline void getTemperatureReadingsCelsius( 1026fe8751cSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1036fe8751cSGeorge Liu const std::string& validChassisPath, const std::string& chassisId) 1046fe8751cSGeorge Liu { 1056fe8751cSGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 1066fe8751cSGeorge Liu "xyz.openbmc_project.Sensor.Value"}; 1076fe8751cSGeorge Liu 1086fe8751cSGeorge Liu sensor_utils::getAllSensorObjects( 1096fe8751cSGeorge Liu validChassisPath, "/xyz/openbmc_project/sensors/temperature", 1106fe8751cSGeorge Liu interfaces, 1, 1116fe8751cSGeorge Liu std::bind_front(handleTemperatureReadingsCelsius, asyncResp, 1126fe8751cSGeorge Liu chassisId)); 1136fe8751cSGeorge Liu } 1146fe8751cSGeorge Liu 1155ae1f7f3Szhanghch05 inline void 1165ae1f7f3Szhanghch05 doThermalMetrics(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1175ae1f7f3Szhanghch05 const std::string& chassisId, 1185ae1f7f3Szhanghch05 const std::optional<std::string>& validChassisPath) 1195ae1f7f3Szhanghch05 { 1205ae1f7f3Szhanghch05 if (!validChassisPath) 1215ae1f7f3Szhanghch05 { 1225ae1f7f3Szhanghch05 messages::resourceNotFound(asyncResp->res, "Chassis", chassisId); 1235ae1f7f3Szhanghch05 return; 1245ae1f7f3Szhanghch05 } 1255ae1f7f3Szhanghch05 1265ae1f7f3Szhanghch05 asyncResp->res.addHeader( 1275ae1f7f3Szhanghch05 boost::beast::http::field::link, 1285ae1f7f3Szhanghch05 "</redfish/v1/JsonSchemas/ThermalMetrics/ThermalMetrics.json>; rel=describedby"); 1295ae1f7f3Szhanghch05 asyncResp->res.jsonValue["@odata.type"] = 1305ae1f7f3Szhanghch05 "#ThermalMetrics.v1_0_1.ThermalMetrics"; 1315ae1f7f3Szhanghch05 asyncResp->res.jsonValue["@odata.id"] = boost::urls::format( 1325ae1f7f3Szhanghch05 "/redfish/v1/Chassis/{}/ThermalSubsystem/ThermalMetrics", chassisId); 1335ae1f7f3Szhanghch05 asyncResp->res.jsonValue["Id"] = "ThermalMetrics"; 1345ae1f7f3Szhanghch05 asyncResp->res.jsonValue["Name"] = "Thermal Metrics"; 1356fe8751cSGeorge Liu 1366fe8751cSGeorge Liu getTemperatureReadingsCelsius(asyncResp, *validChassisPath, chassisId); 1375ae1f7f3Szhanghch05 } 1385ae1f7f3Szhanghch05 1395ae1f7f3Szhanghch05 inline void handleThermalMetricsHead( 1405ae1f7f3Szhanghch05 App& app, const crow::Request& req, 1415ae1f7f3Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1425ae1f7f3Szhanghch05 const std::string& chassisId) 1435ae1f7f3Szhanghch05 { 1445ae1f7f3Szhanghch05 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1455ae1f7f3Szhanghch05 { 1465ae1f7f3Szhanghch05 return; 1475ae1f7f3Szhanghch05 } 1485ae1f7f3Szhanghch05 1495ae1f7f3Szhanghch05 redfish::chassis_utils::getValidChassisPath( 1505ae1f7f3Szhanghch05 asyncResp, chassisId, 1515ae1f7f3Szhanghch05 [asyncResp, 1525ae1f7f3Szhanghch05 chassisId](const std::optional<std::string>& validChassisPath) { 1535ae1f7f3Szhanghch05 if (!validChassisPath) 1545ae1f7f3Szhanghch05 { 155bd79bce8SPatrick Williams messages::resourceNotFound(asyncResp->res, "Chassis", 156bd79bce8SPatrick Williams chassisId); 1575ae1f7f3Szhanghch05 return; 1585ae1f7f3Szhanghch05 } 1595ae1f7f3Szhanghch05 asyncResp->res.addHeader( 1605ae1f7f3Szhanghch05 boost::beast::http::field::link, 1615ae1f7f3Szhanghch05 "</redfish/v1/JsonSchemas/ThermalMetrics/ThermalMetrics.json>; rel=describedby"); 1625ae1f7f3Szhanghch05 }); 1635ae1f7f3Szhanghch05 } 1645ae1f7f3Szhanghch05 1655ae1f7f3Szhanghch05 inline void 1665ae1f7f3Szhanghch05 handleThermalMetricsGet(App& app, const crow::Request& req, 1675ae1f7f3Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1685ae1f7f3Szhanghch05 const std::string& chassisId) 1695ae1f7f3Szhanghch05 { 1705ae1f7f3Szhanghch05 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 1715ae1f7f3Szhanghch05 { 1725ae1f7f3Szhanghch05 return; 1735ae1f7f3Szhanghch05 } 1745ae1f7f3Szhanghch05 1755ae1f7f3Szhanghch05 redfish::chassis_utils::getValidChassisPath( 1765ae1f7f3Szhanghch05 asyncResp, chassisId, 1775ae1f7f3Szhanghch05 std::bind_front(doThermalMetrics, asyncResp, chassisId)); 1785ae1f7f3Szhanghch05 } 1795ae1f7f3Szhanghch05 1805ae1f7f3Szhanghch05 inline void requestRoutesThermalMetrics(App& app) 1815ae1f7f3Szhanghch05 { 1825ae1f7f3Szhanghch05 BMCWEB_ROUTE(app, 1835ae1f7f3Szhanghch05 "/redfish/v1/Chassis/<str>/ThermalSubsystem/ThermalMetrics/") 1845ae1f7f3Szhanghch05 .privileges(redfish::privileges::headThermalMetrics) 1855ae1f7f3Szhanghch05 .methods(boost::beast::http::verb::head)( 1865ae1f7f3Szhanghch05 std::bind_front(handleThermalMetricsHead, std::ref(app))); 1875ae1f7f3Szhanghch05 1885ae1f7f3Szhanghch05 BMCWEB_ROUTE(app, 1895ae1f7f3Szhanghch05 "/redfish/v1/Chassis/<str>/ThermalSubsystem/ThermalMetrics/") 1905ae1f7f3Szhanghch05 .privileges(redfish::privileges::getThermalMetrics) 1915ae1f7f3Szhanghch05 .methods(boost::beast::http::verb::get)( 1925ae1f7f3Szhanghch05 std::bind_front(handleThermalMetricsGet, std::ref(app))); 1935ae1f7f3Szhanghch05 } 1945ae1f7f3Szhanghch05 } // namespace redfish 195