Update physical LEDs as part of Lamp test

- Add the getSubTreePaths method for utils and update all physical
  LEDs.

- Uses GetSubTreePath on Physical LED paths and interfaces and
  updates all the LEDs to ON as part of start or restart of the test.

- When the lamp test is stopped or the timer expires, all the LEDs
  are turned OFF.

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I27727db62fe963a1a7c8b391d73801bcaf9efeec
diff --git a/group.cpp b/group.cpp
index cffae1d..a52bd90 100644
--- a/group.cpp
+++ b/group.cpp
@@ -21,7 +21,7 @@
     if (customCallBack != nullptr)
     {
         // Call the custom callback method
-        customCallBack(value);
+        customCallBack(this, value);
 
         return sdbusplus::xyz::openbmc_project::Led::server::Group::asserted(
             value);
diff --git a/group.hpp b/group.hpp
index bb21fb6..57c33d9 100644
--- a/group.hpp
+++ b/group.hpp
@@ -39,7 +39,7 @@
      */
     Group(sdbusplus::bus::bus& bus, const std::string& objPath,
           Manager& manager, Serialize& serialize,
-          std::function<void(bool)> callBack = nullptr) :
+          std::function<void(Group*, bool)> callBack = nullptr) :
 
         sdbusplus::server::object::object<
             sdbusplus::xyz::openbmc_project::Led::server::Group>(
@@ -76,7 +76,7 @@
 
     /** @brief Custom callback when LED group is asserted
      */
-    std::function<void(bool)> customCallBack;
+    std::function<void(Group*, bool)> customCallBack;
 };
 
 } // namespace led
diff --git a/lamptest.cpp b/lamptest.cpp
index 743bf29..04db6fd 100644
--- a/lamptest.cpp
+++ b/lamptest.cpp
@@ -2,6 +2,8 @@
 
 #include "lamptest.hpp"
 
+#include <phosphor-logging/log.hpp>
+
 namespace phosphor
 {
 namespace led
@@ -10,21 +12,50 @@
 void LampTest::stop()
 {
     timer.setEnabled(false);
+
+    // Set all the Physical action to Off
+    for (const auto& path : physicalLEDPaths)
+    {
+        manager.drivePhysicalLED(path, Layout::Action::Off, 0, 0);
+    }
 }
 
 void LampTest::start()
 {
+    // Get paths of all the Physical LED objects
+    physicalLEDPaths = dBusHandler.getSubTreePaths(PHY_LED_PATH, PHY_LED_IFACE);
+
     // restart lamp test, it contains initiate or reset the timer.
     timer.restart(std::chrono::seconds(LAMP_TEST_TIMEOUT_IN_SECS));
+
+    // Set all the Physical action to On for lamp test
+    for (const auto& path : physicalLEDPaths)
+    {
+        manager.drivePhysicalLED(path, Layout::Action::On, 0, 0);
+    }
 }
 
 void LampTest::timeOutHandler()
 {
+    using namespace phosphor::logging;
+
     // set the Asserted property of lamp test to false
+    if (!groupObj)
+    {
+        log<level::ERR>("the Group object is nullptr");
+        throw std::runtime_error("the Group object is nullptr");
+    }
+
+    groupObj->asserted(false);
 }
 
-void LampTest::requestHandler(bool value)
+void LampTest::requestHandler(Group* group, bool value)
 {
+    if (groupObj == NULL)
+    {
+        groupObj = std::move(group);
+    }
+
     if (value)
     {
         start();
diff --git a/lamptest.hpp b/lamptest.hpp
index ab33887..ffce377 100644
--- a/lamptest.hpp
+++ b/lamptest.hpp
@@ -1,5 +1,6 @@
 #pragma once
 
+#include "group.hpp"
 #include "manager.hpp"
 
 #include <sdeventplus/utility/timer.hpp>
@@ -34,16 +35,17 @@
      */
     LampTest(const sdeventplus::Event& event, Manager& manager) :
         timer(event, std::bind(std::mem_fn(&LampTest::timeOutHandler), this)),
-        manager(manager)
+        manager(manager), groupObj(NULL)
     {}
 
     /** @brief the lamp test request handler
      *
+     *  @param[in]  group    -  Pointer to Group object
      *  @param[in]  value    -  true: start lamptest
      *                          false: stop lamptest
      *  @return
      */
-    void requestHandler(bool value);
+    void requestHandler(Group* group, bool value);
 
   private:
     /** @brief Timer used for LEDs lamp test period */
@@ -52,6 +54,15 @@
     /** @brief Reference to Manager object */
     Manager& manager;
 
+    /** DBusHandler class handles the D-Bus operations */
+    DBusHandler dBusHandler;
+
+    /** @brief Pointer to Group object */
+    Group* groupObj;
+
+    /** all the Physical paths */
+    std::vector<std::string> physicalLEDPaths;
+
     /** @brief Start and restart lamp test depending on what is the current
      *         state. */
     void start();
diff --git a/led-main.cpp b/led-main.cpp
index 7857e91..c1e1a67 100644
--- a/led-main.cpp
+++ b/led-main.cpp
@@ -48,7 +48,7 @@
     groups.emplace_back(std::make_unique<phosphor::led::Group>(
         bus, LAMP_TEST_OBJECT, manager, serialize,
         std::bind(std::mem_fn(&phosphor::led::LampTest::requestHandler),
-                  &lampTest, std::placeholders::_1)));
+                  &lampTest, std::placeholders::_1, std::placeholders::_2)));
 #endif
 
     /** Now create so many dbus objects as there are groups */
diff --git a/manager.cpp b/manager.cpp
index a1c4175..c3c142f 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -14,9 +14,6 @@
 
 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)
diff --git a/manager.hpp b/manager.hpp
index 91f8b53..f75a81b 100644
--- a/manager.hpp
+++ b/manager.hpp
@@ -13,6 +13,9 @@
 {
 using namespace phosphor::led::utils;
 
+static constexpr auto PHY_LED_PATH = "/xyz/openbmc_project/led/physical/";
+static constexpr auto PHY_LED_IFACE = "xyz.openbmc_project.Led.Physical";
+
 /** @class Manager
  *  @brief Manages group of LEDs and applies action on the elements of group
  */
@@ -115,6 +118,17 @@
      */
     void setOperationalStatus(const std::string& path, bool value) const;
 
+    /** @brief Chooses appropriate action to be triggered on physical LED
+     *  and calls into function that applies the actual action.
+     *
+     *  @param[in]  objPath   -  D-Bus object path
+     *  @param[in]  action    -  Intended action to be triggered
+     *  @param[in]  dutyOn    -  Duty Cycle ON percentage
+     *  @param[in]  period    -  Time taken for one blink cycle
+     */
+    void drivePhysicalLED(const std::string& objPath, Layout::Action action,
+                          uint8_t dutyOn, const uint16_t period);
+
   private:
     /** @brief sdbusplus handler */
     sdbusplus::bus::bus& bus;
@@ -143,17 +157,6 @@
      *  @return string equivalent of the passed in enumeration
      */
     static std::string getPhysicalAction(Layout::Action action);
-
-    /** @brief Chooses appropriate action to be triggered on physical LED
-     *  and calls into function that applies the actual action.
-     *
-     *  @param[in]  objPath   -  dbus object path
-     *  @param[in]  action    -  Intended action to be triggered
-     *  @param[in]  dutyOn    -  Duty Cycle ON percentage
-     *  @param[in]  period    -  Time taken for one blink cycle
-     */
-    void drivePhysicalLED(const std::string& objPath, Layout::Action action,
-                          uint8_t dutyOn, const uint16_t period);
 };
 
 } // namespace led
diff --git a/utils.cpp b/utils.cpp
index 6c122f9..116f0c3 100644
--- a/utils.cpp
+++ b/utils.cpp
@@ -114,4 +114,4 @@
 
 } // namespace utils
 } // namespace led
-} // namespace phosphor
\ No newline at end of file
+} // namespace phosphor