xref: /openbmc/phosphor-power/phosphor-power-supply/psu_manager.hpp (revision 2fe5186eaa22350dd2d57cacb682e6ba740f6c41)
12bac8609SBrandon Wyman #pragma once
22bac8609SBrandon Wyman 
3a0f33ce3SBrandon Wyman #include "power_supply.hpp"
4a0f33ce3SBrandon Wyman #include "types.hpp"
5a0f33ce3SBrandon Wyman #include "utility.hpp"
6a0f33ce3SBrandon Wyman 
7a0f33ce3SBrandon Wyman #include <phosphor-logging/log.hpp>
82bac8609SBrandon Wyman #include <sdbusplus/bus/match.hpp>
92bac8609SBrandon Wyman #include <sdeventplus/event.hpp>
102bac8609SBrandon Wyman #include <sdeventplus/utility/timer.hpp>
112bac8609SBrandon Wyman 
12a0f33ce3SBrandon Wyman using namespace phosphor::power::psu;
13a0f33ce3SBrandon Wyman using namespace phosphor::logging;
14a0f33ce3SBrandon Wyman 
152bac8609SBrandon Wyman namespace phosphor
162bac8609SBrandon Wyman {
172bac8609SBrandon Wyman namespace power
182bac8609SBrandon Wyman {
192bac8609SBrandon Wyman namespace manager
202bac8609SBrandon Wyman {
212bac8609SBrandon Wyman 
22*2fe5186eSBrandon Wyman struct json_properties
23*2fe5186eSBrandon Wyman {
24*2fe5186eSBrandon Wyman     int pollInterval;
25*2fe5186eSBrandon Wyman };
26*2fe5186eSBrandon Wyman 
272bac8609SBrandon Wyman /**
282bac8609SBrandon Wyman  * @class PSUManager
292bac8609SBrandon Wyman  *
302bac8609SBrandon Wyman  * This class will create an object used to manage and monitor a list of power
312bac8609SBrandon Wyman  * supply devices.
322bac8609SBrandon Wyman  */
332bac8609SBrandon Wyman class PSUManager
342bac8609SBrandon Wyman {
352bac8609SBrandon Wyman   public:
362bac8609SBrandon Wyman     PSUManager() = delete;
372bac8609SBrandon Wyman     ~PSUManager() = default;
382bac8609SBrandon Wyman     PSUManager(const PSUManager&) = delete;
392bac8609SBrandon Wyman     PSUManager& operator=(const PSUManager&) = delete;
402bac8609SBrandon Wyman     PSUManager(PSUManager&&) = delete;
412bac8609SBrandon Wyman     PSUManager& operator=(PSUManager&&) = delete;
422bac8609SBrandon Wyman 
432bac8609SBrandon Wyman     /**
442bac8609SBrandon Wyman      * Constructor
452bac8609SBrandon Wyman      *
462bac8609SBrandon Wyman      * @param[in] bus - D-Bus bus object
472bac8609SBrandon Wyman      * @param[in] e - event object
48*2fe5186eSBrandon Wyman      * @param[in] configfile - string path to the configuration file
492bac8609SBrandon Wyman      */
502bac8609SBrandon Wyman     PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
51*2fe5186eSBrandon Wyman                const std::string& configfile) :
52*2fe5186eSBrandon Wyman         bus(bus)
532bac8609SBrandon Wyman     {
54*2fe5186eSBrandon Wyman         // Parse out the JSON properties
55*2fe5186eSBrandon Wyman         json_properties properties = {0};
56*2fe5186eSBrandon Wyman         getJSONProperties(configfile, properties);
57*2fe5186eSBrandon Wyman 
58*2fe5186eSBrandon Wyman         using namespace sdeventplus;
59*2fe5186eSBrandon Wyman         auto pollInterval = std::chrono::milliseconds(properties.pollInterval);
60*2fe5186eSBrandon Wyman         timer = std::make_unique<utility::Timer<ClockId::Monotonic>>(
61*2fe5186eSBrandon Wyman             e, std::bind(&PSUManager::analyze, this), pollInterval);
62*2fe5186eSBrandon Wyman 
63a0f33ce3SBrandon Wyman         // Subscribe to power state changes
64a0f33ce3SBrandon Wyman         powerService = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);
65a0f33ce3SBrandon Wyman         powerOnMatch = std::make_unique<sdbusplus::bus::match_t>(
66a0f33ce3SBrandon Wyman             bus,
67a0f33ce3SBrandon Wyman             sdbusplus::bus::match::rules::propertiesChanged(POWER_OBJ_PATH,
68a0f33ce3SBrandon Wyman                                                             POWER_IFACE),
69a0f33ce3SBrandon Wyman             [this](auto& msg) { this->powerStateChanged(msg); });
70a0f33ce3SBrandon Wyman 
71a0f33ce3SBrandon Wyman         initialize();
722bac8609SBrandon Wyman     }
732bac8609SBrandon Wyman 
74*2fe5186eSBrandon Wyman     void getJSONProperties(const std::string& path, json_properties& p)
75*2fe5186eSBrandon Wyman     {
76*2fe5186eSBrandon Wyman         nlohmann::json configFileJSON = util::loadJSONFromFile(path.c_str());
77*2fe5186eSBrandon Wyman 
78*2fe5186eSBrandon Wyman         if (configFileJSON == nullptr)
79*2fe5186eSBrandon Wyman         {
80*2fe5186eSBrandon Wyman             throw std::runtime_error("Failed to load JSON configuration file");
81*2fe5186eSBrandon Wyman         }
82*2fe5186eSBrandon Wyman 
83*2fe5186eSBrandon Wyman         if (!configFileJSON.contains("pollInterval"))
84*2fe5186eSBrandon Wyman         {
85*2fe5186eSBrandon Wyman             throw std::runtime_error("Missing required pollInterval property");
86*2fe5186eSBrandon Wyman         }
87*2fe5186eSBrandon Wyman 
88*2fe5186eSBrandon Wyman         p.pollInterval = configFileJSON.at("pollInterval");
89*2fe5186eSBrandon Wyman     }
90*2fe5186eSBrandon Wyman 
912bac8609SBrandon Wyman     /**
922bac8609SBrandon Wyman      * Initializes the manager.
932bac8609SBrandon Wyman      *
942bac8609SBrandon Wyman      * Get current BMC state, ...
952bac8609SBrandon Wyman      */
962bac8609SBrandon Wyman     void initialize()
972bac8609SBrandon Wyman     {
98a0f33ce3SBrandon Wyman         // When state = 1, system is powered on
99a0f33ce3SBrandon Wyman         int32_t state = 0;
100a0f33ce3SBrandon Wyman 
101a0f33ce3SBrandon Wyman         try
102a0f33ce3SBrandon Wyman         {
103a0f33ce3SBrandon Wyman             // Use getProperty utility function to get power state.
104a0f33ce3SBrandon Wyman             util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH,
105a0f33ce3SBrandon Wyman                                        powerService, bus, state);
106a0f33ce3SBrandon Wyman 
107a0f33ce3SBrandon Wyman             if (state)
108a0f33ce3SBrandon Wyman             {
109a0f33ce3SBrandon Wyman                 powerOn = true;
110a0f33ce3SBrandon Wyman             }
111a0f33ce3SBrandon Wyman             else
112a0f33ce3SBrandon Wyman             {
113a0f33ce3SBrandon Wyman                 powerOn = false;
114a0f33ce3SBrandon Wyman             }
115a0f33ce3SBrandon Wyman         }
116a0f33ce3SBrandon Wyman         catch (std::exception& e)
117a0f33ce3SBrandon Wyman         {
118a0f33ce3SBrandon Wyman             log<level::INFO>("Failed to get power state. Assuming it is off.");
119a0f33ce3SBrandon Wyman             powerOn = false;
120a0f33ce3SBrandon Wyman         }
121a0f33ce3SBrandon Wyman 
122a0f33ce3SBrandon Wyman         clearFaults();
123a0f33ce3SBrandon Wyman         updateInventory();
1242bac8609SBrandon Wyman     }
1252bac8609SBrandon Wyman 
1262bac8609SBrandon Wyman     /**
1272bac8609SBrandon Wyman      * Starts the timer to start monitoring the list of devices.
1282bac8609SBrandon Wyman      */
1292bac8609SBrandon Wyman     int run()
1302bac8609SBrandon Wyman     {
131*2fe5186eSBrandon Wyman         return timer->get_event().loop();
1322bac8609SBrandon Wyman     }
1332bac8609SBrandon Wyman 
1342bac8609SBrandon Wyman     /**
1352bac8609SBrandon Wyman      * This function will be called in various situations in order to clear
1362bac8609SBrandon Wyman      * any fault status bits that may have been set, in order to start over
1372bac8609SBrandon Wyman      * with a clean state. Presence changes and power state changes will want
1382bac8609SBrandon Wyman      * to clear any faults logged.
1392bac8609SBrandon Wyman      */
1402bac8609SBrandon Wyman     void clearFaults()
1412bac8609SBrandon Wyman     {
142a0f33ce3SBrandon Wyman         for (auto& psu : psus)
143a0f33ce3SBrandon Wyman         {
144a0f33ce3SBrandon Wyman             psu.clearFaults();
145a0f33ce3SBrandon Wyman         }
1462bac8609SBrandon Wyman     }
1472bac8609SBrandon Wyman 
1482bac8609SBrandon Wyman   private:
1492bac8609SBrandon Wyman     /**
1502bac8609SBrandon Wyman      * The D-Bus object
1512bac8609SBrandon Wyman      */
1522bac8609SBrandon Wyman     sdbusplus::bus::bus& bus;
1532bac8609SBrandon Wyman 
1542bac8609SBrandon Wyman     /**
1552bac8609SBrandon Wyman      * The timer that runs to periodically check the power supplies.
1562bac8609SBrandon Wyman      */
157*2fe5186eSBrandon Wyman     std::unique_ptr<
158*2fe5186eSBrandon Wyman         sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
159*2fe5186eSBrandon Wyman         timer;
1602bac8609SBrandon Wyman 
1612bac8609SBrandon Wyman     /**
1622bac8609SBrandon Wyman      * Analyze the status of each of the power supplies.
1632bac8609SBrandon Wyman      */
1642bac8609SBrandon Wyman     void analyze()
1652bac8609SBrandon Wyman     {
166a0f33ce3SBrandon Wyman         for (auto& psu : psus)
167a0f33ce3SBrandon Wyman         {
168a0f33ce3SBrandon Wyman             psu.analyze();
169a0f33ce3SBrandon Wyman         }
1702bac8609SBrandon Wyman     }
1712bac8609SBrandon Wyman 
1722bac8609SBrandon Wyman     /** @brief True if the power is on. */
1732bac8609SBrandon Wyman     bool powerOn = false;
1742bac8609SBrandon Wyman 
175a0f33ce3SBrandon Wyman     /** @brief Used as part of subscribing to power on state changes*/
176a0f33ce3SBrandon Wyman     std::string powerService;
177a0f33ce3SBrandon Wyman 
1782bac8609SBrandon Wyman     /** @brief Used to subscribe to D-Bus power on state changes */
1792bac8609SBrandon Wyman     std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
1802bac8609SBrandon Wyman 
1812bac8609SBrandon Wyman     /**
1822bac8609SBrandon Wyman      * @brief Callback for power state property changes
1832bac8609SBrandon Wyman      *
1842bac8609SBrandon Wyman      * Process changes to the powered on state property for the system.
1852bac8609SBrandon Wyman      *
1862bac8609SBrandon Wyman      * @param[in] msg - Data associated with the power state signal
1872bac8609SBrandon Wyman      */
1882bac8609SBrandon Wyman     void powerStateChanged(sdbusplus::message::message& msg);
1892bac8609SBrandon Wyman 
1902bac8609SBrandon Wyman     /**
1912bac8609SBrandon Wyman      * @brief Adds properties to the inventory.
1922bac8609SBrandon Wyman      *
1932bac8609SBrandon Wyman      * Reads the values from the devices and writes them to the associated
1942bac8609SBrandon Wyman      * power supply D-Bus inventory objects.
1952bac8609SBrandon Wyman      *
1962bac8609SBrandon Wyman      * This needs to be done on startup, and each time the presence state
1972bac8609SBrandon Wyman      * changes.
1982bac8609SBrandon Wyman      */
199a0f33ce3SBrandon Wyman     void updateInventory()
200a0f33ce3SBrandon Wyman     {
201a0f33ce3SBrandon Wyman         for (auto& psu : psus)
202a0f33ce3SBrandon Wyman         {
203a0f33ce3SBrandon Wyman             psu.updateInventory();
204a0f33ce3SBrandon Wyman         }
205a0f33ce3SBrandon Wyman     }
206a0f33ce3SBrandon Wyman 
207a0f33ce3SBrandon Wyman     /**
208a0f33ce3SBrandon Wyman      * @brief The vector for power supplies.
209a0f33ce3SBrandon Wyman      */
210a0f33ce3SBrandon Wyman     std::vector<PowerSupply> psus;
2112bac8609SBrandon Wyman };
2122bac8609SBrandon Wyman 
2132bac8609SBrandon Wyman } // namespace manager
2142bac8609SBrandon Wyman } // namespace power
2152bac8609SBrandon Wyman } // namespace phosphor
216