blob: b3877b7ba54cee2370d70d923eb6e3cba4924dcf [file] [log] [blame]
Brandon Wyman2bac8602019-09-12 18:12:21 -05001#pragma once
2
Brandon Wymana0f33ce2019-10-17 18:32:29 -05003#include "power_supply.hpp"
4#include "types.hpp"
5#include "utility.hpp"
6
7#include <phosphor-logging/log.hpp>
Brandon Wyman2bac8602019-09-12 18:12:21 -05008#include <sdbusplus/bus/match.hpp>
9#include <sdeventplus/event.hpp>
10#include <sdeventplus/utility/timer.hpp>
11
Brandon Wymana0f33ce2019-10-17 18:32:29 -050012using namespace phosphor::power::psu;
13using namespace phosphor::logging;
14
Brandon Wyman2bac8602019-09-12 18:12:21 -050015namespace phosphor
16{
17namespace power
18{
19namespace manager
20{
21
Brandon Wyman2fe51862019-11-25 16:43:21 -060022struct json_properties
23{
24 int pollInterval;
25};
26
Brandon Wyman2bac8602019-09-12 18:12:21 -050027/**
28 * @class PSUManager
29 *
30 * This class will create an object used to manage and monitor a list of power
31 * supply devices.
32 */
33class PSUManager
34{
35 public:
36 PSUManager() = delete;
37 ~PSUManager() = default;
38 PSUManager(const PSUManager&) = delete;
39 PSUManager& operator=(const PSUManager&) = delete;
40 PSUManager(PSUManager&&) = delete;
41 PSUManager& operator=(PSUManager&&) = delete;
42
43 /**
44 * Constructor
45 *
46 * @param[in] bus - D-Bus bus object
47 * @param[in] e - event object
Brandon Wyman2fe51862019-11-25 16:43:21 -060048 * @param[in] configfile - string path to the configuration file
Brandon Wyman2bac8602019-09-12 18:12:21 -050049 */
50 PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
Brandon Wyman2fe51862019-11-25 16:43:21 -060051 const std::string& configfile) :
52 bus(bus)
Brandon Wyman2bac8602019-09-12 18:12:21 -050053 {
Brandon Wyman2fe51862019-11-25 16:43:21 -060054 // Parse out the JSON properties
55 json_properties properties = {0};
56 getJSONProperties(configfile, properties);
57
58 using namespace sdeventplus;
59 auto pollInterval = std::chrono::milliseconds(properties.pollInterval);
60 timer = std::make_unique<utility::Timer<ClockId::Monotonic>>(
61 e, std::bind(&PSUManager::analyze, this), pollInterval);
62
Brandon Wymana0f33ce2019-10-17 18:32:29 -050063 // Subscribe to power state changes
64 powerService = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);
65 powerOnMatch = std::make_unique<sdbusplus::bus::match_t>(
66 bus,
67 sdbusplus::bus::match::rules::propertiesChanged(POWER_OBJ_PATH,
68 POWER_IFACE),
69 [this](auto& msg) { this->powerStateChanged(msg); });
70
71 initialize();
Brandon Wyman2bac8602019-09-12 18:12:21 -050072 }
73
Brandon Wyman2fe51862019-11-25 16:43:21 -060074 void getJSONProperties(const std::string& path, json_properties& p)
75 {
76 nlohmann::json configFileJSON = util::loadJSONFromFile(path.c_str());
77
78 if (configFileJSON == nullptr)
79 {
80 throw std::runtime_error("Failed to load JSON configuration file");
81 }
82
83 if (!configFileJSON.contains("pollInterval"))
84 {
85 throw std::runtime_error("Missing required pollInterval property");
86 }
87
88 p.pollInterval = configFileJSON.at("pollInterval");
89 }
90
Brandon Wyman2bac8602019-09-12 18:12:21 -050091 /**
92 * Initializes the manager.
93 *
94 * Get current BMC state, ...
95 */
96 void initialize()
97 {
Brandon Wymana0f33ce2019-10-17 18:32:29 -050098 // When state = 1, system is powered on
99 int32_t state = 0;
100
101 try
102 {
103 // Use getProperty utility function to get power state.
104 util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH,
105 powerService, bus, state);
106
107 if (state)
108 {
109 powerOn = true;
110 }
111 else
112 {
113 powerOn = false;
114 }
115 }
116 catch (std::exception& e)
117 {
118 log<level::INFO>("Failed to get power state. Assuming it is off.");
119 powerOn = false;
120 }
121
122 clearFaults();
123 updateInventory();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500124 }
125
126 /**
127 * Starts the timer to start monitoring the list of devices.
128 */
129 int run()
130 {
Brandon Wyman2fe51862019-11-25 16:43:21 -0600131 return timer->get_event().loop();
Brandon Wyman2bac8602019-09-12 18:12:21 -0500132 }
133
134 /**
135 * This function will be called in various situations in order to clear
136 * any fault status bits that may have been set, in order to start over
137 * with a clean state. Presence changes and power state changes will want
138 * to clear any faults logged.
139 */
140 void clearFaults()
141 {
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500142 for (auto& psu : psus)
143 {
144 psu.clearFaults();
145 }
Brandon Wyman2bac8602019-09-12 18:12:21 -0500146 }
147
148 private:
149 /**
150 * The D-Bus object
151 */
152 sdbusplus::bus::bus& bus;
153
154 /**
155 * The timer that runs to periodically check the power supplies.
156 */
Brandon Wyman2fe51862019-11-25 16:43:21 -0600157 std::unique_ptr<
158 sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
159 timer;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500160
161 /**
162 * Analyze the status of each of the power supplies.
163 */
164 void analyze()
165 {
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500166 for (auto& psu : psus)
167 {
168 psu.analyze();
169 }
Brandon Wyman2bac8602019-09-12 18:12:21 -0500170 }
171
172 /** @brief True if the power is on. */
173 bool powerOn = false;
174
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500175 /** @brief Used as part of subscribing to power on state changes*/
176 std::string powerService;
177
Brandon Wyman2bac8602019-09-12 18:12:21 -0500178 /** @brief Used to subscribe to D-Bus power on state changes */
179 std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;
180
181 /**
Brandon Wyman2bac8602019-09-12 18:12:21 -0500182 * @brief Callback for power state property changes
183 *
184 * Process changes to the powered on state property for the system.
185 *
186 * @param[in] msg - Data associated with the power state signal
187 */
188 void powerStateChanged(sdbusplus::message::message& msg);
189
190 /**
191 * @brief Adds properties to the inventory.
192 *
193 * Reads the values from the devices and writes them to the associated
194 * power supply D-Bus inventory objects.
195 *
196 * This needs to be done on startup, and each time the presence state
197 * changes.
198 */
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500199 void updateInventory()
200 {
201 for (auto& psu : psus)
202 {
203 psu.updateInventory();
204 }
205 }
206
207 /**
208 * @brief The vector for power supplies.
209 */
210 std::vector<PowerSupply> psus;
Brandon Wyman2bac8602019-09-12 18:12:21 -0500211};
212
213} // namespace manager
214} // namespace power
215} // namespace phosphor