Add the method to set Functional property based on Group state

When a particular LED Group asserted property is set to true, then the
functional state of that FRU is false and vice-versa. This commit adds
that behavior. Functional status is defined in
xyz.openbmc_project.State.Decorator.OperationalStatus interface.

Tested: When manually set the Asserted property to true by the D-Bus,
we can see that the Functional is updated to false.

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I6fa7a4c41363263d345b6b5335056fad15efb78c
diff --git a/manager.cpp b/manager.cpp
index d19eeae..a1c4175 100644
--- a/manager.cpp
+++ b/manager.cpp
@@ -186,5 +186,57 @@
     }
 }
 
+// Set OperationalStatus functional according to the asserted state of the group
+void Manager::setOperationalStatus(const std::string& path, bool value) const
+{
+    using namespace phosphor::logging;
+
+    // Get endpoints from the rType
+    std::string fru = path + "/fru_fault";
+
+    // endpoint contains the vector of strings, where each string is a Inventory
+    // D-Bus object that this, associated with this LED Group D-Bus object
+    // pointed to by fru_fault
+    PropertyValue endpoint{};
+
+    try
+    {
+        endpoint = dBusHandler.getProperty(
+            fru, "xyz.openbmc_project.Association", "endpoints");
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        log<level::ERR>("Failed to get endpoints property",
+                        entry("ERROR=%s", e.what()),
+                        entry("PATH=%s", fru.c_str()));
+        return;
+    }
+
+    auto& endpoints = std::get<std::vector<std::string>>(endpoint);
+    if (endpoints.empty())
+    {
+        return;
+    }
+
+    for (const auto& fruInstancePath : endpoints)
+    {
+        // Set OperationalStatus by fru instance path
+        try
+        {
+            PropertyValue functionalValue{value};
+            dBusHandler.setProperty(
+                fruInstancePath,
+                "xyz.openbmc_project.State.Decorator.OperationalStatus",
+                "Functional", functionalValue);
+        }
+        catch (const sdbusplus::exception::SdBusError& e)
+        {
+            log<level::ERR>("Failed to set Functional property",
+                            entry("ERROR=%s", e.what()),
+                            entry("PATH=%s", fruInstancePath.c_str()));
+        }
+    }
+}
+
 } // namespace led
 } // namespace phosphor