1 #pragma once 2 #include <dbus_utility.hpp> 3 #include <query.hpp> 4 #include <utils/json_utils.hpp> 5 6 namespace redfish 7 { 8 /** 9 * @brief Fill cable specific properties. 10 * @param[in,out] resp HTTP response. 11 * @param[in] ec Error code corresponding to Async method call. 12 * @param[in] properties List of Cable Properties key/value pairs. 13 */ 14 inline void 15 fillCableProperties(crow::Response& resp, 16 const boost::system::error_code ec, 17 const dbus::utility::DBusPropertiesMap& properties) 18 { 19 if (ec) 20 { 21 BMCWEB_LOG_DEBUG << "DBUS response error " << ec; 22 messages::internalError(resp); 23 return; 24 } 25 26 for (const auto& [propKey, propVariant] : properties) 27 { 28 if (propKey == "CableTypeDescription") 29 { 30 const std::string* cableTypeDescription = 31 std::get_if<std::string>(&propVariant); 32 if (cableTypeDescription == nullptr) 33 { 34 messages::internalError(resp); 35 return; 36 } 37 resp.jsonValue["CableType"] = *cableTypeDescription; 38 } 39 else if (propKey == "Length") 40 { 41 const double* cableLength = std::get_if<double>(&propVariant); 42 if (cableLength == nullptr) 43 { 44 messages::internalError(resp); 45 return; 46 } 47 48 if (!std::isfinite(*cableLength)) 49 { 50 if (std::isnan(*cableLength)) 51 { 52 continue; 53 } 54 messages::internalError(resp); 55 return; 56 } 57 58 resp.jsonValue["LengthMeters"] = *cableLength; 59 } 60 } 61 } 62 63 /** 64 * @brief Api to get Cable properties. 65 * @param[in,out] asyncResp Async HTTP response. 66 * @param[in] cableObjectPath Object path of the Cable. 67 * @param[in] serviceMap A map to hold Service and corresponding 68 * interface list for the given cable id. 69 */ 70 inline void 71 getCableProperties(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 72 const std::string& cableObjectPath, 73 const dbus::utility::MapperServiceMap& serviceMap) 74 { 75 BMCWEB_LOG_DEBUG << "Get Properties for cable " << cableObjectPath; 76 77 for (const auto& [service, interfaces] : serviceMap) 78 { 79 for (const auto& interface : interfaces) 80 { 81 if (interface != "xyz.openbmc_project.Inventory.Item.Cable") 82 { 83 continue; 84 } 85 86 crow::connections::systemBus->async_method_call( 87 [asyncResp]( 88 const boost::system::error_code ec, 89 const dbus::utility::DBusPropertiesMap& properties) { 90 fillCableProperties(asyncResp->res, ec, properties); 91 }, 92 service, cableObjectPath, "org.freedesktop.DBus.Properties", 93 "GetAll", interface); 94 } 95 } 96 } 97 98 /** 99 * The Cable schema 100 */ 101 inline void requestRoutesCable(App& app) 102 { 103 BMCWEB_ROUTE(app, "/redfish/v1/Cables/<str>/") 104 .privileges(redfish::privileges::getCable) 105 .methods(boost::beast::http::verb::get)( 106 [&app](const crow::Request& req, 107 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 108 const std::string& cableId) { 109 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 110 { 111 return; 112 } 113 BMCWEB_LOG_DEBUG << "Cable Id: " << cableId; 114 auto respHandler = 115 [asyncResp, 116 cableId](const boost::system::error_code ec, 117 const dbus::utility::MapperGetSubTreeResponse& subtree) { 118 if (ec.value() == EBADR) 119 { 120 messages::resourceNotFound(asyncResp->res, "Cable", cableId); 121 return; 122 } 123 124 if (ec) 125 { 126 BMCWEB_LOG_ERROR << "DBUS response error " << ec; 127 messages::internalError(asyncResp->res); 128 return; 129 } 130 131 for (const auto& [objectPath, serviceMap] : subtree) 132 { 133 sdbusplus::message::object_path path(objectPath); 134 if (path.filename() != cableId) 135 { 136 continue; 137 } 138 139 asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable"; 140 asyncResp->res.jsonValue["@odata.id"] = 141 "/redfish/v1/Cables/" + cableId; 142 asyncResp->res.jsonValue["Id"] = cableId; 143 asyncResp->res.jsonValue["Name"] = "Cable"; 144 145 getCableProperties(asyncResp, objectPath, serviceMap); 146 return; 147 } 148 messages::resourceNotFound(asyncResp->res, "Cable", cableId); 149 }; 150 151 crow::connections::systemBus->async_method_call( 152 respHandler, "xyz.openbmc_project.ObjectMapper", 153 "/xyz/openbmc_project/object_mapper", 154 "xyz.openbmc_project.ObjectMapper", "GetSubTree", 155 "/xyz/openbmc_project/inventory", 0, 156 std::array<const char*, 1>{ 157 "xyz.openbmc_project.Inventory.Item.Cable"}); 158 }); 159 } 160 161 /** 162 * Collection of Cable resource instances 163 */ 164 inline void requestRoutesCableCollection(App& app) 165 { 166 BMCWEB_ROUTE(app, "/redfish/v1/Cables/") 167 .privileges(redfish::privileges::getCableCollection) 168 .methods(boost::beast::http::verb::get)( 169 [&app](const crow::Request& req, 170 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 171 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 172 { 173 return; 174 } 175 asyncResp->res.jsonValue["@odata.type"] = 176 "#CableCollection.CableCollection"; 177 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables"; 178 asyncResp->res.jsonValue["Name"] = "Cable Collection"; 179 asyncResp->res.jsonValue["Description"] = "Collection of Cable Entries"; 180 181 collection_util::getCollectionMembers( 182 asyncResp, "/redfish/v1/Cables", 183 {"xyz.openbmc_project.Inventory.Item.Cable"}); 184 }); 185 } 186 187 } // namespace redfish 188