Add utility for D-Bus
Putting all D-Bus related operation to the utils file.
Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I934e519bca43b73da01ed09fc73f6c7cdc795e1f
diff --git a/Makefile.am b/Makefile.am
index 5edc8f9..4b91f58 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,7 +6,8 @@
led-main.cpp \
manager.cpp \
group.cpp \
- serialize.cpp
+ serialize.cpp \
+ utils.cpp
if !WANTS_JSON
BUILT_SOURCES = led-gen.hpp
diff --git a/led-main.cpp b/led-main.cpp
index 0b060dc..7dc0488 100644
--- a/led-main.cpp
+++ b/led-main.cpp
@@ -9,13 +9,14 @@
#include "ledlayout.hpp"
#include "manager.hpp"
#include "serialize.hpp"
+#include "utils.hpp"
#include <iostream>
int main(void)
{
/** @brief Dbus constructs used by LED Group manager */
- sdbusplus::bus::bus bus = sdbusplus::bus::new_default();
+ auto& bus = phosphor::led::utils::DBusHandler::getBus();
#ifdef LED_USE_JSON
auto systemLedMap = loadJsonConfig(LED_JSON_FILE);
diff --git a/manager.cpp b/manager.cpp
index 7741933..d19eeae 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -12,6 +12,11 @@
namespace led
{
+using namespace phosphor::logging;
+
+static constexpr auto PHY_LED_PATH = "/xyz/openbmc_project/led/physical/";
+static constexpr auto PHY_LED_IFACE = "xyz.openbmc_project.Led.Physical";
+
// Assert -or- De-assert
bool Manager::setGroupState(const std::string& path, bool assert,
group& ledsAssert, group& ledsDeAssert)
@@ -101,16 +106,6 @@
/** @brief Run through the map and apply action on the LEDs */
void Manager::driveLEDs(group& ledsAssert, group& ledsDeAssert)
{
- using namespace phosphor::logging;
- // Map of physical LED dbus paths to their Service providers
- populateObjectMap();
-
- if (phyLeds.empty())
- {
- // Error message is inside the map construction logic.
- return;
- }
-
// This order of LED operation is important.
if (ledsDeAssert.size())
{
@@ -142,24 +137,30 @@
Layout::Action action, uint8_t dutyOn,
const uint16_t period)
{
- using namespace phosphor::logging;
-
- auto service = phyLeds.find(objPath);
- if (service == phyLeds.end() || service->second.empty())
+ try
{
- log<level::ERR>("No service providers for physical LED",
- entry("PATH=%s", objPath.c_str()));
- return;
+ // If Blink, set its property
+ if (action == Layout::Action::Blink)
+ {
+ PropertyValue dutyOnValue{dutyOn};
+ PropertyValue periodValue{period};
+
+ dBusHandler.setProperty(objPath, PHY_LED_IFACE, "DutyOn",
+ dutyOnValue);
+ dBusHandler.setProperty(objPath, PHY_LED_IFACE, "Period",
+ periodValue);
+ }
+
+ PropertyValue actionValue{getPhysicalAction(action)};
+ dBusHandler.setProperty(objPath, PHY_LED_IFACE, "State", actionValue);
+ }
+ catch (const std::exception& e)
+ {
+ log<level::ERR>("Error setting property for physical LED",
+ entry("ERROR=%s", e.what()),
+ entry("OBJECT_PATH=%s", objPath.c_str()));
}
- // If Blink, set its property
- if (action == Layout::Action::Blink)
- {
- drivePhysicalLED(service->second, objPath, "DutyOn", dutyOn);
- drivePhysicalLED(service->second, objPath, "Period", period);
- }
- drivePhysicalLED(service->second, objPath, "State",
- getPhysicalAction(action));
return;
}
@@ -185,69 +186,5 @@
}
}
-/** Populates a map with physical LED paths to its service providers */
-void Manager::populateObjectMap()
-{
- using namespace phosphor::logging;
-
- // Mapper dbus constructs
- constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
- constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
- constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
-
- // Needed to be passed to get the SubTree level
- auto depth = 0;
-
- // Clean start
- phyLeds.clear();
-
- // Make a mapper call
- auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
- MAPPER_IFACE, "GetSubTree");
- // Cook rest of the things.
- mapperCall.append(PHY_LED_PATH);
- mapperCall.append(depth);
- mapperCall.append(std::vector<std::string>({PHY_LED_IFACE}));
-
- auto reply = bus.call(mapperCall);
- if (reply.is_method_error())
- {
- // Its okay if we do not see a corresponding physical LED.
- log<level::INFO>("Error looking up Physical LED services",
- entry("PATH=%s", PHY_LED_PATH));
- return;
- }
-
- // Response by mapper in the case of success
- std::map<std::string, std::map<std::string, std::vector<std::string>>>
- objectTree;
-
- // This is the dict of object paths - service names - interfaces
- try
- {
- reply.read(objectTree);
- }
- catch (const sdbusplus::exception::SdBusError& e)
- {
- log<level::ERR>("Failed to parse Physical LED service lookup",
- entry("ERROR=%s", e.what()),
- entry("REPLY_SIG=%s", reply.get_signature()));
- return;
- }
- if (objectTree.empty())
- {
- log<level::INFO>("Physical LED lookup did not return any services",
- entry("PATH=%s", PHY_LED_PATH));
- return;
- }
-
- // Now construct our path -> Service name map.
- for (const auto& iter : objectTree)
- {
- phyLeds.emplace(iter.first, iter.second.begin()->first);
- }
- return;
-}
-
} // namespace led
} // namespace phosphor
diff --git a/manager.hpp b/manager.hpp
index 0cc5cf6..390c8fe 100644
--- a/manager.hpp
+++ b/manager.hpp
@@ -1,8 +1,7 @@
#pragma once
#include "ledlayout.hpp"
-
-#include <sdbusplus/bus.hpp>
+#include "utils.hpp"
#include <map>
#include <set>
@@ -12,11 +11,7 @@
{
namespace led
{
-
-/** @brief Physical LED dbus constructs */
-constexpr auto PHY_LED_PATH = "/xyz/openbmc_project/led/physical/";
-constexpr auto PHY_LED_IFACE = "xyz.openbmc_project.Led.Physical";
-constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
+using namespace phosphor::led::utils;
/** @class Manager
* @brief Manages group of LEDs and applies action on the elements of group
@@ -117,6 +112,9 @@
/** Map of physical LED path to service name */
std::map<std::string, std::string> phyLeds{};
+ /** DBusHandler class handles the D-Bus operations */
+ DBusHandler dBusHandler;
+
/** @brief Pointers to groups that are in asserted state */
std::set<const group*> assertedGroups;
@@ -146,36 +144,6 @@
*/
void drivePhysicalLED(const std::string& objPath, Layout::Action action,
uint8_t dutyOn, const uint16_t period);
-
- /** @brief Makes a dbus call to a passed in service name.
- * This is now the physical LED controller
- *
- * @param[in] service - dbus service name
- * @param[in] objPath - dbus object path
- * @param[in] property - property to be written to
- * @param[in] value - Value to write
- */
- template <typename T>
- void drivePhysicalLED(const std::string& service,
- const std::string& objPath,
- const std::string& property, const T& value)
- {
- std::variant<T> data = value;
-
- auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
- DBUS_PROPERTY_IFACE, "Set");
- method.append(PHY_LED_IFACE);
- method.append(property);
- method.append(data);
-
- // There will be exceptions going forward and hence don't need a
- // response
- bus.call_noreply(method);
- return;
- }
-
- /** @brief Populates map of Physical LED paths to service name */
- void populateObjectMap();
};
} // namespace led
diff --git a/test/Makefile.am b/test/Makefile.am
index 3941c5c..0a6ef3a 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -9,4 +9,4 @@
utest_CXXFLAGS = $(PTHREAD_CFLAGS)
utest_LDFLAGS = -lgtest_main -lgtest $(PTHREAD_LIBS) $(OESDK_TESTCASE_FLAGS) $(SYSTEMD_LIBS) $(PHOSPHOR_LOGGING_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS)
utest_SOURCES = utest.cpp utest-led-json.cpp utest-serialize.cpp
-utest_LDADD = $(top_builddir)/manager.o $(top_builddir)/serialize.o
+utest_LDADD = $(top_builddir)/manager.o $(top_builddir)/serialize.o $(top_builddir)/utils.o
diff --git a/utils.cpp b/utils.cpp
new file mode 100644
index 0000000..136d20f
--- /dev/null
+++ b/utils.cpp
@@ -0,0 +1,72 @@
+#include "utils.hpp"
+
+#include <phosphor-logging/log.hpp>
+
+namespace phosphor
+{
+namespace led
+{
+namespace utils
+{
+
+using namespace phosphor::logging;
+
+// Get service name
+const std::string DBusHandler::getService(const std::string& path,
+ const std::string& interface) const
+{
+
+ using InterfaceList = std::vector<std::string>;
+ std::map<std::string, std::vector<std::string>> mapperResponse;
+
+ auto& bus = DBusHandler::getBus();
+
+ auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_OBJ_PATH,
+ MAPPER_IFACE, "GetObject");
+ mapper.append(path, InterfaceList({interface}));
+
+ auto mapperResponseMsg = bus.call(mapper);
+ if (mapperResponseMsg.is_method_error())
+ {
+ log<level::ERR>("Failed to invoke ObjectMapper method",
+ entry("OBJECT_PATH=%s", path.c_str()),
+ entry("INTERFACE=%s", interface.c_str()));
+ return "";
+ }
+
+ mapperResponseMsg.read(mapperResponse);
+ if (mapperResponse.empty())
+ {
+ log<level::ERR>("Failed to read getService mapper response",
+ entry("OBJECT_PATH=%s", path.c_str()),
+ entry("INTERFACE=%s", interface.c_str()));
+ return "";
+ }
+
+ // the value here will be the service name
+ return mapperResponse.cbegin()->first;
+}
+
+// Set property
+void DBusHandler::setProperty(const std::string& objectPath,
+ const std::string& interface,
+ const std::string& propertyName,
+ const PropertyValue& value) const
+{
+ auto& bus = DBusHandler::getBus();
+ auto service = getService(objectPath, interface);
+ if (service.empty())
+ {
+ return;
+ }
+
+ auto method = bus.new_method_call(service.c_str(), objectPath.c_str(),
+ DBUS_PROPERTY_IFACE, "Set");
+ method.append(interface.c_str(), propertyName.c_str(), value);
+
+ bus.call_noreply(method);
+}
+
+} // namespace utils
+} // namespace led
+} // namespace phosphor
\ No newline at end of file
diff --git a/utils.hpp b/utils.hpp
new file mode 100644
index 0000000..edb0315
--- /dev/null
+++ b/utils.hpp
@@ -0,0 +1,67 @@
+#pragma once
+#include <sdbusplus/server.hpp>
+
+#include <map>
+#include <vector>
+namespace phosphor
+{
+namespace led
+{
+namespace utils
+{
+constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper";
+constexpr auto MAPPER_OBJ_PATH = "/xyz/openbmc_project/object_mapper";
+constexpr auto MAPPER_IFACE = "xyz.openbmc_project.ObjectMapper";
+constexpr auto DBUS_PROPERTY_IFACE = "org.freedesktop.DBus.Properties";
+
+// The value of the property(type: variant, contains some basic types)
+// Eg: uint8_t : dutyOn, uint16_t : Period, std::string : Name
+using PropertyValue = std::variant<uint8_t, uint16_t, std::string>;
+
+/**
+ * @class DBusHandler
+ *
+ * Wrapper class to handle the D-Bus calls
+ *
+ * This class contains the APIs to handle the D-Bus calls.
+ */
+class DBusHandler
+{
+ public:
+ /** @brief Get the bus connection. */
+ static auto& getBus()
+ {
+ static auto bus = sdbusplus::bus::new_default();
+ return bus;
+ }
+
+ /**
+ * @brief Get service name by the path and interface of the DBus.
+ *
+ * @param[in] path - D-Bus object path
+ * @param[in] interface - D-Bus Interface
+ *
+ * @return std::string - the D-Bus service name
+ *
+ */
+ const std::string getService(const std::string& path,
+ const std::string& interface) const;
+
+ /** @brief Set D-Bus property
+ *
+ * @param[in] objectPath - D-Bus object path
+ * @param[in] interface - D-Bus interface
+ * @param[in] propertyName - D-Bus property name
+ * @param[in] value - The value to be set
+ *
+ * @throw sdbusplus::exception::SdBusError when it fails
+ */
+ void setProperty(const std::string& objectPath,
+ const std::string& interface,
+ const std::string& propertyName,
+ const PropertyValue& value) const;
+};
+
+} // namespace utils
+} // namespace led
+} // namespace phosphor