#pragma once #include #include #include #include #include #include #include #include namespace util { namespace detail { namespace errors = sdbusplus::xyz::openbmc_project::Common::Error; } // namespace detail /** @brief Alias for PropertiesChanged signal callbacks. */ template using Properties = std::map>; namespace sdbusplus { /** @brief Get the bus connection. */ static auto& getBus() __attribute__((pure)); static auto& getBus() { static auto bus = ::sdbusplus::bus::new_default(); return bus; } /** @brief Invoke a method. */ template static auto callMethod(::sdbusplus::bus_t& bus, const std::string& busName, const std::string& path, const std::string& interface, const std::string& method, Args&&... args) { auto reqMsg = bus.new_method_call(busName.c_str(), path.c_str(), interface.c_str(), method.c_str()); reqMsg.append(std::forward(args)...); try { return bus.call(reqMsg); } catch (const std::exception& e) { lg2::error("Failed to invoke DBus method: {PATH}, {INTF}, {METHOD}", "PATH", path, "INTF", interface, "METHOD", method); phosphor::logging::elog(); } } /** @brief Invoke a method. */ template static auto callMethod(const std::string& busName, const std::string& path, const std::string& interface, const std::string& method, Args&&... args) { return callMethod(getBus(), busName, path, interface, method, std::forward(args)...); } /** @brief Invoke a method and read the response. */ template static auto callMethodAndRead(::sdbusplus::bus_t& bus, const std::string& busName, const std::string& path, const std::string& interface, const std::string& method, Args&&... args) { ::sdbusplus::message_t respMsg = callMethod( bus, busName, path, interface, method, std::forward(args)...); Ret resp; respMsg.read(resp); return resp; } /** @brief Invoke a method and read the response. */ template static auto callMethodAndRead(const std::string& busName, const std::string& path, const std::string& interface, const std::string& method, Args&&... args) { return callMethodAndRead(getBus(), busName, path, interface, method, std::forward(args)...); } /** @brief Get service from the mapper. */ static auto getService(::sdbusplus::bus_t& bus, const std::string& path, const std::string& interface) { using namespace std::literals::string_literals; using GetObject = std::map>; auto mapperResp = callMethodAndRead( bus, "xyz.openbmc_project.ObjectMapper"s, "/xyz/openbmc_project/object_mapper"s, "xyz.openbmc_project.ObjectMapper"s, "GetObject"s, path, GetObject::mapped_type{interface}); if (mapperResp.empty()) { lg2::error("Object not found. {PATH}, {INTF}", "PATH", path, "INTF", interface); phosphor::logging::elog(); } return mapperResp.begin()->first; } /** @brief Get a property without mapper lookup. */ template static auto getProperty(::sdbusplus::bus_t& bus, const std::string& busName, const std::string& path, const std::string& interface, const std::string& property) { using namespace std::literals::string_literals; auto msg = callMethod(bus, busName, path, "org.freedesktop.DBus.Properties"s, "Get"s, interface, property); ::std::variant value; msg.read(value); return std::get(value); } /** @brief Get a property without mapper lookup. */ template static auto getProperty(const std::string& busName, const std::string& path, const std::string& interface, const std::string& property) { return getProperty(getBus(), busName, path, interface, property); } /** @brief Get a property with mapper lookup. */ template static auto getProperty(::sdbusplus::bus_t& bus, const std::string& path, const std::string& interface, const std::string& property) { return getProperty(bus, getService(bus, path, interface), path, interface, property); } /** @brief Get a property with mapper lookup. */ template static auto getProperty(const std::string& path, const std::string& interface, const std::string& property) { return getProperty(getBus(), path, interface, property); } } // namespace sdbusplus } // namespace util