1 #include "operational-status-monitor.hpp"
2 
3 #include <phosphor-logging/elog.hpp>
4 
5 namespace phosphor
6 {
7 namespace led
8 {
9 namespace Operational
10 {
11 namespace status
12 {
13 namespace monitor
14 {
15 using namespace phosphor::logging;
16 
17 void Monitor::matchHandler(sdbusplus::message::message& msg)
18 {
19     // Get the ObjectPath of the `xyz.openbmc_project.Inventory.Manager`
20     // service
21     std::string invObjectPath = msg.get_path();
22 
23     // Get all the properties of
24     // "xyz.openbmc_project.State.Decorator.OperationalStatus" interface
25     std::string interfaceName{};
26     std::map<std::string, std::variant<bool>> properties;
27     msg.read(interfaceName, properties);
28 
29     const auto it = properties.find("Functional");
30     if (it != properties.end())
31     {
32         const bool* value = std::get_if<bool>(&it->second);
33         if (!value)
34         {
35             log<level::ERR>("Faild to get the Functional property",
36                             entry("INVENTORY_PATH=%s", invObjectPath.c_str()));
37             return;
38         }
39 
40         // See if the Inventory D-Bus object has an association with LED groups
41         // D-Bus object.
42         auto ledGroupPath = getLedGroupPaths(invObjectPath);
43         if (ledGroupPath.empty())
44         {
45             log<level::INFO>("The inventory D-Bus object is not associated "
46                              "with the LED group D-Bus object.",
47                              entry("INVENTORY_PATH=%s", invObjectPath.c_str()));
48             return;
49         }
50 
51         // Update the Asserted property by the Functional property value.
52         updateAssertedProperty(ledGroupPath, *value);
53     }
54 }
55 
56 const std::vector<std::string>
57     Monitor::getLedGroupPaths(const std::string& inventoryPath) const
58 {
59     // Get endpoints from the rType
60     std::string faultLedAssociation = inventoryPath + "/fault_led_group";
61 
62     // endpoint contains the vector of strings, where each string is a Inventory
63     // D-Bus object that this, associated with this LED Group D-Bus object
64     // pointed to by fru_fault
65     PropertyValue endpoint{};
66 
67     try
68     {
69         endpoint = dBusHandler.getProperty(faultLedAssociation,
70                                            "xyz.openbmc_project.Association",
71                                            "endpoints");
72     }
73     catch (const sdbusplus::exception::SdBusError& e)
74     {
75         log<level::ERR>("Failed to get endpoints property",
76                         entry("ERROR=%s", e.what()),
77                         entry("PATH=%s", faultLedAssociation.c_str()));
78 
79         return {};
80     }
81 
82     auto& endpoints = std::get<std::vector<std::string>>(endpoint);
83 
84     return endpoints;
85 }
86 
87 void Monitor::updateAssertedProperty(
88     const std::vector<std::string>& ledGroupPaths, bool value)
89 {
90     for (const auto& path : ledGroupPaths)
91     {
92         try
93         {
94             // Call "Group Asserted --> true" if the value of Functional is
95             // false Call "Group Asserted --> false" if the value of Functional
96             // is true
97             PropertyValue assertedValue{!value};
98             dBusHandler.setProperty(path, "xyz.openbmc_project.Led.Group",
99                                     "Asserted", assertedValue);
100         }
101         catch (const sdbusplus::exception::SdBusError& e)
102         {
103             log<level::ERR>("Failed to set Asserted property",
104                             entry("ERROR=%s", e.what()),
105                             entry("PATH=%s", path.c_str()));
106         }
107     }
108 }
109 } // namespace monitor
110 } // namespace status
111 } // namespace Operational
112 } // namespace led
113 } // namespace phosphor
114