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