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