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, 121 "#Cable.v1_0_0.Cable", cableId); 122 return; 123 } 124 125 if (ec) 126 { 127 BMCWEB_LOG_ERROR << "DBUS response error " << ec; 128 messages::internalError(asyncResp->res); 129 return; 130 } 131 132 for (const auto& [objectPath, serviceMap] : subtree) 133 { 134 sdbusplus::message::object_path path(objectPath); 135 if (path.filename() != cableId) 136 { 137 continue; 138 } 139 140 asyncResp->res.jsonValue["@odata.type"] = "#Cable.v1_0_0.Cable"; 141 asyncResp->res.jsonValue["@odata.id"] = 142 "/redfish/v1/Cables/" + cableId; 143 asyncResp->res.jsonValue["Id"] = cableId; 144 asyncResp->res.jsonValue["Name"] = "Cable"; 145 146 getCableProperties(asyncResp, objectPath, serviceMap); 147 return; 148 } 149 messages::resourceNotFound(asyncResp->res, "Cable", cableId); 150 }; 151 152 crow::connections::systemBus->async_method_call( 153 respHandler, "xyz.openbmc_project.ObjectMapper", 154 "/xyz/openbmc_project/object_mapper", 155 "xyz.openbmc_project.ObjectMapper", "GetSubTree", 156 "/xyz/openbmc_project/inventory", 0, 157 std::array<const char*, 1>{ 158 "xyz.openbmc_project.Inventory.Item.Cable"}); 159 }); 160 } 161 162 /** 163 * Collection of Cable resource instances 164 */ 165 inline void requestRoutesCableCollection(App& app) 166 { 167 BMCWEB_ROUTE(app, "/redfish/v1/Cables/") 168 .privileges(redfish::privileges::getCableCollection) 169 .methods(boost::beast::http::verb::get)( 170 [&app](const crow::Request& req, 171 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 172 if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 173 { 174 return; 175 } 176 asyncResp->res.jsonValue["@odata.type"] = 177 "#CableCollection.CableCollection"; 178 asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/Cables"; 179 asyncResp->res.jsonValue["Name"] = "Cable Collection"; 180 asyncResp->res.jsonValue["Description"] = "Collection of Cable Entries"; 181 182 collection_util::getCollectionMembers( 183 asyncResp, "/redfish/v1/Cables", 184 {"xyz.openbmc_project.Inventory.Item.Cable"}); 185 }); 186 } 187 188 } // namespace redfish 189