1 #pragma once
2 
3 #include "power_supply.hpp"
4 #include "types.hpp"
5 #include "utility.hpp"
6 
7 #include <phosphor-logging/log.hpp>
8 #include <sdbusplus/bus/match.hpp>
9 #include <sdeventplus/event.hpp>
10 #include <sdeventplus/utility/timer.hpp>
11 
12 struct sys_properties
13 {
14     int pollInterval;
15     int minPowerSupplies;
16     int maxPowerSupplies;
17 };
18 
19 using namespace phosphor::power::psu;
20 using namespace phosphor::logging;
21 
22 namespace phosphor
23 {
24 namespace power
25 {
26 namespace manager
27 {
28 
29 /**
30  * @class PSUManager
31  *
32  * This class will create an object used to manage and monitor a list of power
33  * supply devices.
34  */
35 class PSUManager
36 {
37   public:
38     PSUManager() = delete;
39     ~PSUManager() = default;
40     PSUManager(const PSUManager&) = delete;
41     PSUManager& operator=(const PSUManager&) = delete;
42     PSUManager(PSUManager&&) = delete;
43     PSUManager& operator=(PSUManager&&) = delete;
44 
45     /**
46      * Constructor
47      *
48      * @param[in] bus - D-Bus bus object
49      * @param[in] e - event object
50      * @param[in] configfile - string path to the configuration file
51      */
52     PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
53                const std::string& configfile);
54 
55     void getJSONProperties(const std::string& path, sdbusplus::bus::bus& bus,
56                            sys_properties& p,
57                            std::vector<std::unique_ptr<PowerSupply>>& psus);
58 
59     /**
60      * Initializes the manager.
61      *
62      * Get current BMC state, ...
63      */
64     void initialize()
65     {
66         // When state = 1, system is powered on
67         int32_t state = 0;
68 
69         try
70         {
71             // Use getProperty utility function to get power state.
72             util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH,
73                                        powerService, bus, state);
74 
75             if (state)
76             {
77                 powerOn = true;
78             }
79             else
80             {
81                 powerOn = false;
82             }
83         }
84         catch (std::exception& e)
85         {
86             log<level::INFO>("Failed to get power state. Assuming it is off.");
87             powerOn = false;
88         }
89 
90         clearFaults();
91         updateInventory();
92     }
93 
94     /**
95      * Starts the timer to start monitoring the list of devices.
96      */
97     int run()
98     {
99         return timer->get_event().loop();
100     }
101 
102     /**
103      * This function will be called in various situations in order to clear
104      * any fault status bits that may have been set, in order to start over
105      * with a clean state. Presence changes and power state changes will want
106      * to clear any faults logged.
107      */
108     void clearFaults()
109     {
110         for (auto& psu : psus)
111         {
112             psu->clearFaults();
113         }
114 
115         faultLogged = false;
116     }
117 
118   private:
119     /**
120      * The D-Bus object
121      */
122     sdbusplus::bus::bus& bus;
123 
124     /**
125      * The timer that runs to periodically check the power supplies.
126      */
127     std::unique_ptr<
128         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
129         timer;
130 
131     /**
132      * Analyze the status of each of the power supplies.
133      */
134     void analyze()
135     {
136         for (auto& psu : psus)
137         {
138             psu->analyze();
139         }
140 
141         for (auto& psu : psus)
142         {
143             // TODO: Fault priorities #918
144             if (!faultLogged && psu->isFaulted())
145             {
146                 if (psu->hasInputFault())
147                 {
148                     // TODO: Create error log
149                 }
150 
151                 if (psu->hasMFRFault())
152                 {
153                     // TODO: Create error log
154                 }
155 
156                 if (psu->hasVINUVFault())
157                 {
158                     // TODO: Create error log
159                 }
160             }
161         }
162     }
163 
164     /** @brief True if the power is on. */
165     bool powerOn = false;
166 
167     /** @brief True if fault logged. Clear in clearFaults(). */
168     bool faultLogged = false;
169 
170     /** @brief Used as part of subscribing to power on state changes*/
171     std::string powerService;
172 
173     /** @brief Used to subscribe to D-Bus power on state changes */
174     std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
175 
176     /**
177      * @brief Callback for power state property changes
178      *
179      * Process changes to the powered on state property for the system.
180      *
181      * @param[in] msg - Data associated with the power state signal
182      */
183     void powerStateChanged(sdbusplus::message::message& msg);
184 
185     /**
186      * @brief Adds properties to the inventory.
187      *
188      * Reads the values from the devices and writes them to the associated
189      * power supply D-Bus inventory objects.
190      *
191      * This needs to be done on startup, and each time the presence state
192      * changes.
193      */
194     void updateInventory()
195     {
196         for (auto& psu : psus)
197         {
198             psu->updateInventory();
199         }
200     }
201 
202     /**
203      * @brief Minimum number of power supplies to operate.
204      */
205     int minPSUs = 1;
206 
207     /**
208      * @brief Maximum number of power supplies possible.
209      */
210     int maxPSUs = 1;
211 
212     /**
213      * @brief The vector for power supplies.
214      */
215     std::vector<std::unique_ptr<PowerSupply>> psus;
216 };
217 
218 } // namespace manager
219 } // namespace power
220 } // namespace phosphor
221