blob: 0fcd56692e9c50094d2e2cae3f1ff9e5832210fb [file] [log] [blame]
Brandon Wymana0f33ce2019-10-17 18:32:29 -05001#include "psu_manager.hpp"
2
3#include "utility.hpp"
4
Brandon Wymanaed1f752019-11-25 18:10:52 -06005using namespace phosphor::logging;
6
Brandon Wyman63ea78b2020-09-24 16:49:09 -05007namespace phosphor::power::manager
Brandon Wymana0f33ce2019-10-17 18:32:29 -05008{
9
Brandon Wymanaed1f752019-11-25 18:10:52 -060010PSUManager::PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
11 const std::string& configfile) :
12 bus(bus)
13{
14 // Parse out the JSON properties
15 sys_properties properties;
16 getJSONProperties(configfile, bus, properties, psus);
17
18 using namespace sdeventplus;
Jay Meyerda364552020-06-26 16:14:11 -050019 auto interval = std::chrono::milliseconds(1000);
Brandon Wymanaed1f752019-11-25 18:10:52 -060020 timer = std::make_unique<utility::Timer<ClockId::Monotonic>>(
21 e, std::bind(&PSUManager::analyze, this), interval);
22
23 minPSUs = {properties.minPowerSupplies};
24 maxPSUs = {properties.maxPowerSupplies};
25
26 // Subscribe to power state changes
27 powerService = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);
28 powerOnMatch = std::make_unique<sdbusplus::bus::match_t>(
29 bus,
30 sdbusplus::bus::match::rules::propertiesChanged(POWER_OBJ_PATH,
31 POWER_IFACE),
32 [this](auto& msg) { this->powerStateChanged(msg); });
33
34 initialize();
35}
36
37void PSUManager::getJSONProperties(
38 const std::string& path, sdbusplus::bus::bus& bus, sys_properties& p,
39 std::vector<std::unique_ptr<PowerSupply>>& psus)
40{
41 nlohmann::json configFileJSON = util::loadJSONFromFile(path.c_str());
42
43 if (configFileJSON == nullptr)
44 {
45 throw std::runtime_error("Failed to load JSON configuration file");
46 }
47
48 if (!configFileJSON.contains("SystemProperties"))
49 {
50 throw std::runtime_error("Missing required SystemProperties");
51 }
52
53 if (!configFileJSON.contains("PowerSupplies"))
54 {
55 throw std::runtime_error("Missing required PowerSupplies");
56 }
57
58 auto sysProps = configFileJSON["SystemProperties"];
59
Brandon Wymanaed1f752019-11-25 18:10:52 -060060 if (sysProps.contains("MinPowerSupplies"))
61 {
62 p.minPowerSupplies = sysProps["MinPowerSupplies"];
63 }
64 else
65 {
66 p.minPowerSupplies = 0;
67 }
68
69 if (sysProps.contains("MaxPowerSupplies"))
70 {
71 p.maxPowerSupplies = sysProps["MaxPowerSupplies"];
72 }
73 else
74 {
75 p.maxPowerSupplies = 0;
76 }
77
78 for (auto psuJSON : configFileJSON["PowerSupplies"])
79 {
Brandon Wymanc63941c2020-01-27 16:49:33 -060080 if (psuJSON.contains("Inventory") && psuJSON.contains("Bus") &&
81 psuJSON.contains("Address"))
Brandon Wymanaed1f752019-11-25 18:10:52 -060082 {
83 std::string invpath = psuJSON["Inventory"];
Brandon Wymanc63941c2020-01-27 16:49:33 -060084 std::uint8_t i2cbus = psuJSON["Bus"];
85 std::string i2caddr = psuJSON["Address"];
86 auto psu =
87 std::make_unique<PowerSupply>(bus, invpath, i2cbus, i2caddr);
Brandon Wymanaed1f752019-11-25 18:10:52 -060088 psus.emplace_back(std::move(psu));
89 }
Brandon Wymanc63941c2020-01-27 16:49:33 -060090 else
91 {
92 log<level::ERR>("Insufficient PowerSupply properties");
93 }
Brandon Wymanaed1f752019-11-25 18:10:52 -060094 }
95
96 if (psus.empty())
97 {
98 throw std::runtime_error("No power supplies to monitor");
99 }
100}
101
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500102void PSUManager::powerStateChanged(sdbusplus::message::message& msg)
103{
104 int32_t state = 0;
105 std::string msgSensor;
Patrick Williamsabe49412020-05-13 17:59:47 -0500106 std::map<std::string, std::variant<int32_t>> msgData;
Brandon Wymana0f33ce2019-10-17 18:32:29 -0500107 msg.read(msgSensor, msgData);
108
109 // Check if it was the Present property that changed.
110 auto valPropMap = msgData.find("state");
111 if (valPropMap != msgData.end())
112 {
113 state = std::get<int32_t>(valPropMap->second);
114
115 // Power is on when state=1. Clear faults.
116 if (state)
117 {
118 powerOn = true;
119 clearFaults();
120 }
121 else
122 {
123 powerOn = false;
124 }
125 }
126}
127
Brandon Wyman63ea78b2020-09-24 16:49:09 -0500128void PSUManager::analyze()
129{
130 for (auto& psu : psus)
131 {
132 psu->analyze();
133 }
134
135 for (auto& psu : psus)
136 {
137 // TODO: Fault priorities #918
138 if (!faultLogged && psu->isFaulted())
139 {
140 if (psu->hasInputFault())
141 {
142 // TODO: Create error log
143 }
144
145 if (psu->hasMFRFault())
146 {
147 // TODO: Create error log
148 }
149
150 if (psu->hasVINUVFault())
151 {
152 // TODO: Create error log
153 }
154 }
155 }
156}
157
158} // namespace phosphor::power::manager