15ae1f7f3Szhanghch05 #pragma once 25ae1f7f3Szhanghch05 35ae1f7f3Szhanghch05 #include "app.hpp" 4*6fe8751cSGeorge Liu #include "dbus_utility.hpp" 55ae1f7f3Szhanghch05 #include "query.hpp" 65ae1f7f3Szhanghch05 #include "registries/privilege_registry.hpp" 75ae1f7f3Szhanghch05 #include "utils/chassis_utils.hpp" 8*6fe8751cSGeorge Liu #include "utils/json_utils.hpp" 9*6fe8751cSGeorge Liu #include "utils/sensor_utils.hpp" 105ae1f7f3Szhanghch05 11*6fe8751cSGeorge Liu #include <boost/system/error_code.hpp> 12*6fe8751cSGeorge Liu 13*6fe8751cSGeorge Liu #include <array> 145ae1f7f3Szhanghch05 #include <functional> 155ae1f7f3Szhanghch05 #include <memory> 165ae1f7f3Szhanghch05 #include <optional> 175ae1f7f3Szhanghch05 #include <string> 18*6fe8751cSGeorge Liu #include <string_view> 195ae1f7f3Szhanghch05 205ae1f7f3Szhanghch05 namespace redfish 215ae1f7f3Szhanghch05 { 22*6fe8751cSGeorge Liu inline void afterGetTemperatureValue( 23*6fe8751cSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 24*6fe8751cSGeorge Liu const std::string& chassisId, const std::string& path, 25*6fe8751cSGeorge Liu const boost::system::error_code& ec, 26*6fe8751cSGeorge Liu const dbus::utility::DBusPropertiesMap& valuesDict) 27*6fe8751cSGeorge Liu { 28*6fe8751cSGeorge Liu if (ec) 29*6fe8751cSGeorge Liu { 30*6fe8751cSGeorge Liu if (ec.value() != EBADR) 31*6fe8751cSGeorge Liu { 32*6fe8751cSGeorge Liu BMCWEB_LOG_ERROR("DBUS response error for getAllProperties {}", 33*6fe8751cSGeorge Liu ec.value()); 34*6fe8751cSGeorge Liu messages::internalError(asyncResp->res); 35*6fe8751cSGeorge Liu } 36*6fe8751cSGeorge Liu return; 37*6fe8751cSGeorge Liu } 38*6fe8751cSGeorge Liu 39*6fe8751cSGeorge Liu nlohmann::json item = nlohmann::json::object(); 40*6fe8751cSGeorge Liu 41*6fe8751cSGeorge Liu /* Don't return an error for a failure to fill in properties from any of 42*6fe8751cSGeorge Liu * the sensors in the list. Just skip it. 43*6fe8751cSGeorge Liu */ 44*6fe8751cSGeorge Liu if (sensor_utils::objectExcerptToJson( 45*6fe8751cSGeorge Liu path, chassisId, sensor_utils::ChassisSubNode::thermalMetricsNode, 46*6fe8751cSGeorge Liu "temperature", valuesDict, item)) 47*6fe8751cSGeorge Liu { 48*6fe8751cSGeorge Liu nlohmann::json& temperatureReadings = 49*6fe8751cSGeorge Liu asyncResp->res.jsonValue["TemperatureReadingsCelsius"]; 50*6fe8751cSGeorge Liu nlohmann::json::array_t* temperatureArray = 51*6fe8751cSGeorge Liu temperatureReadings.get_ptr<nlohmann::json::array_t*>(); 52*6fe8751cSGeorge Liu if (temperatureArray == nullptr) 53*6fe8751cSGeorge Liu { 54*6fe8751cSGeorge Liu BMCWEB_LOG_ERROR("Missing TemperatureReadingsCelsius Json array"); 55*6fe8751cSGeorge Liu messages::internalError(asyncResp->res); 56*6fe8751cSGeorge Liu return; 57*6fe8751cSGeorge Liu } 58*6fe8751cSGeorge Liu 59*6fe8751cSGeorge Liu temperatureArray->emplace_back(std::move(item)); 60*6fe8751cSGeorge Liu asyncResp->res.jsonValue["TemperatureReadingsCelsius@odata.count"] = 61*6fe8751cSGeorge Liu temperatureArray->size(); 62*6fe8751cSGeorge Liu 63*6fe8751cSGeorge Liu json_util::sortJsonArrayByKey(*temperatureArray, "DataSourceUri"); 64*6fe8751cSGeorge Liu } 65*6fe8751cSGeorge Liu } 66*6fe8751cSGeorge Liu 67*6fe8751cSGeorge Liu inline void handleTemperatureReadingsCelsius( 68*6fe8751cSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 69*6fe8751cSGeorge Liu const std::string& chassisId, const boost::system::error_code& ec, 70*6fe8751cSGeorge Liu const sensor_utils::SensorServicePathList& sensorsServiceAndPath) 71*6fe8751cSGeorge Liu { 72*6fe8751cSGeorge Liu if (ec) 73*6fe8751cSGeorge Liu { 74*6fe8751cSGeorge Liu if (ec.value() != EBADR) 75*6fe8751cSGeorge Liu { 76*6fe8751cSGeorge Liu BMCWEB_LOG_ERROR("DBUS response error for getAssociatedSubTree {}", 77*6fe8751cSGeorge Liu ec.value()); 78*6fe8751cSGeorge Liu messages::internalError(asyncResp->res); 79*6fe8751cSGeorge Liu } 80*6fe8751cSGeorge Liu return; 81*6fe8751cSGeorge Liu } 82*6fe8751cSGeorge Liu 83*6fe8751cSGeorge Liu asyncResp->res.jsonValue["TemperatureReadingsCelsius"] = 84*6fe8751cSGeorge Liu nlohmann::json::array_t(); 85*6fe8751cSGeorge Liu asyncResp->res.jsonValue["TemperatureReadingsCelsius@odata.count"] = 0; 86*6fe8751cSGeorge Liu 87*6fe8751cSGeorge Liu for (const auto& [service, sensorPath] : sensorsServiceAndPath) 88*6fe8751cSGeorge Liu { 89*6fe8751cSGeorge Liu sdbusplus::asio::getAllProperties( 90*6fe8751cSGeorge Liu *crow::connections::systemBus, service, sensorPath, 91*6fe8751cSGeorge Liu "xyz.openbmc_project.Sensor.Value", 92*6fe8751cSGeorge Liu [asyncResp, chassisId, 93*6fe8751cSGeorge Liu sensorPath](const boost::system::error_code& ec1, 94*6fe8751cSGeorge Liu const dbus::utility::DBusPropertiesMap& properties) { 95*6fe8751cSGeorge Liu afterGetTemperatureValue(asyncResp, chassisId, sensorPath, ec1, 96*6fe8751cSGeorge Liu properties); 97*6fe8751cSGeorge Liu }); 98*6fe8751cSGeorge Liu } 99*6fe8751cSGeorge Liu } 100*6fe8751cSGeorge Liu 101*6fe8751cSGeorge Liu inline void getTemperatureReadingsCelsius( 102*6fe8751cSGeorge Liu const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 103*6fe8751cSGeorge Liu const std::string& validChassisPath, const std::string& chassisId) 104*6fe8751cSGeorge Liu { 105*6fe8751cSGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 106*6fe8751cSGeorge Liu "xyz.openbmc_project.Sensor.Value"}; 107*6fe8751cSGeorge Liu 108*6fe8751cSGeorge Liu sensor_utils::getAllSensorObjects( 109*6fe8751cSGeorge Liu validChassisPath, "/xyz/openbmc_project/sensors/temperature", 110*6fe8751cSGeorge Liu interfaces, 1, 111*6fe8751cSGeorge Liu std::bind_front(handleTemperatureReadingsCelsius, asyncResp, 112*6fe8751cSGeorge Liu chassisId)); 113*6fe8751cSGeorge Liu } 114*6fe8751cSGeorge 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"; 135*6fe8751cSGeorge Liu 136*6fe8751cSGeorge 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