| #pragma once |
| |
| #include "async_resp.hpp" |
| #include "dbus_utility.hpp" |
| #include "error_messages.hpp" |
| #include "managed_store.hpp" |
| #include "utility.hpp" |
| |
| #include <array> |
| #include <string_view> |
| #include <unordered_map> |
| |
| #ifdef UNIT_TEST_BUILD |
| #include "test/g3/mock_managed_store.hpp" // NOLINT |
| #endif |
| |
| namespace redfish |
| { |
| |
| namespace fan_utils |
| { |
| |
| constexpr std::array<std::string_view, 1> fanInterfaces = { |
| "xyz.openbmc_project.Configuration.Fan"}; |
| |
| inline void fillFanProperties( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& objectPath, |
| const dbus::utility::DBusPropertiesMap& properties, |
| const std::shared_ptr<std::unordered_map<std::string, std::string>>& |
| fanSensorToInventoryPath) |
| { |
| for (const auto& [propKey, propVariant] : properties) |
| { |
| if (propKey == "TachSensor") |
| { |
| const std::string* tachSensor = |
| std::get_if<std::string>(&propVariant); |
| if (tachSensor == nullptr) |
| { |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| (*fanSensorToInventoryPath)[*tachSensor] = objectPath; |
| } |
| else if (propKey == "PWMSensor") |
| { |
| const std::string* pwmSensor = |
| std::get_if<std::string>(&propVariant); |
| if (pwmSensor == nullptr) |
| { |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| (*fanSensorToInventoryPath)[*pwmSensor] = objectPath; |
| } |
| } |
| } |
| |
| template <typename Callback> |
| inline void getFanInventory( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::shared_ptr<std::unordered_map<std::string, std::string>>& |
| fanSensorToInventoryPath, |
| Callback callback) |
| { |
| managedStore::ManagedObjectStoreContext requestContext(asyncResp); |
| managedStore::GetManagedObjectStore()->getSubTree( |
| "/xyz/openbmc_project/inventory", 0, fanInterfaces, requestContext, |
| [asyncResp, fanSensorToInventoryPath, requestContext, |
| callback{callback}]( |
| const boost::system::error_code ec, |
| const dbus::utility::MapperGetSubTreeResponse& subtree) { |
| if (ec) |
| { |
| BMCWEB_LOG_DEBUG << "DBUS response error"; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| if (subtree.empty()) |
| { |
| callback(); |
| return; |
| } |
| |
| auto fanConfigurationsQueried = std::make_shared<int>(subtree.size()); |
| for (const auto& [objectPath, serviceMap] : subtree) |
| { |
| for (const auto& [service, interfaces] : serviceMap) |
| { |
| for (const auto& interface : interfaces) |
| { |
| if (interface != fanInterfaces[0]) |
| { |
| continue; |
| } |
| managedStore::GetManagedObjectStore()->getAllProperties( |
| service, objectPath, interface, requestContext, |
| [asyncResp, fanSensorToInventoryPath, objectPath, |
| callback, fanConfigurationsQueried]( |
| const boost::system::error_code& ec, |
| const dbus::utility::DBusPropertiesMap& |
| properties) { |
| if (ec) |
| { |
| BMCWEB_LOG_DEBUG << "DBUS response error " << ec; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| fillFanProperties(asyncResp, objectPath, properties, |
| fanSensorToInventoryPath); |
| |
| if (*fanConfigurationsQueried <= 0) |
| { |
| BMCWEB_LOG_ERROR << "Unaccounted fan configuration"; |
| messages::internalError(asyncResp->res); |
| return; |
| } |
| |
| if (*fanConfigurationsQueried == 1) |
| { |
| callback(); |
| } |
| --(*fanConfigurationsQueried); |
| }); |
| } |
| } |
| } |
| }); |
| } |
| |
| inline void AddThermalSubsystemLink( |
| const sdbusplus::message::object_path& fanInventoryPath, |
| nlohmann::json& sensorJson) |
| { |
| nlohmann::json::object_t obj; |
| obj["@odata.id"] = crow::utility::urlFromPieces( |
| "redfish", "v1", "Chassis", fanInventoryPath.parent_path().filename(), |
| "ThermalSubsystem", "Fans", fanInventoryPath.filename()); |
| sensorJson["RelatedItem"] = nlohmann::json::array_t{std::move(obj)}; |
| } |
| |
| inline void AddRelatedItemForFanSensor( |
| const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, |
| const std::string& sensorName) |
| { |
| auto fanSensorToInventoryPath = |
| std::make_shared<std::unordered_map<std::string, std::string>>(); |
| getFanInventory(asyncResp, fanSensorToInventoryPath, |
| [asyncResp, sensorName, fanSensorToInventoryPath]() { |
| auto findFanObjectPath = fanSensorToInventoryPath->find(sensorName); |
| if (findFanObjectPath != fanSensorToInventoryPath->end()) |
| { |
| sdbusplus::message::object_path fanInventoryPath( |
| findFanObjectPath->second); |
| AddThermalSubsystemLink(fanInventoryPath, asyncResp->res.jsonValue); |
| } |
| }); |
| } |
| |
| } // namespace fan_utils |
| } // namespace redfish |