1 #include "psu_manager.hpp" 2 3 #include "utility.hpp" 4 5 using namespace phosphor::logging; 6 7 namespace phosphor 8 { 9 namespace power 10 { 11 namespace manager 12 { 13 14 PSUManager::PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e, 15 const std::string& configfile) : 16 bus(bus) 17 { 18 // Parse out the JSON properties 19 sys_properties properties; 20 getJSONProperties(configfile, bus, properties, psus); 21 22 using namespace sdeventplus; 23 auto interval = std::chrono::milliseconds(properties.pollInterval); 24 timer = std::make_unique<utility::Timer<ClockId::Monotonic>>( 25 e, std::bind(&PSUManager::analyze, this), interval); 26 27 minPSUs = {properties.minPowerSupplies}; 28 maxPSUs = {properties.maxPowerSupplies}; 29 30 // Subscribe to power state changes 31 powerService = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus); 32 powerOnMatch = std::make_unique<sdbusplus::bus::match_t>( 33 bus, 34 sdbusplus::bus::match::rules::propertiesChanged(POWER_OBJ_PATH, 35 POWER_IFACE), 36 [this](auto& msg) { this->powerStateChanged(msg); }); 37 38 initialize(); 39 } 40 41 void PSUManager::getJSONProperties( 42 const std::string& path, sdbusplus::bus::bus& bus, sys_properties& p, 43 std::vector<std::unique_ptr<PowerSupply>>& psus) 44 { 45 nlohmann::json configFileJSON = util::loadJSONFromFile(path.c_str()); 46 47 if (configFileJSON == nullptr) 48 { 49 throw std::runtime_error("Failed to load JSON configuration file"); 50 } 51 52 if (!configFileJSON.contains("SystemProperties")) 53 { 54 throw std::runtime_error("Missing required SystemProperties"); 55 } 56 57 if (!configFileJSON.contains("PowerSupplies")) 58 { 59 throw std::runtime_error("Missing required PowerSupplies"); 60 } 61 62 auto sysProps = configFileJSON["SystemProperties"]; 63 64 if (!sysProps.contains("pollInterval")) 65 { 66 throw std::runtime_error("Missing required pollInterval property"); 67 } 68 69 p.pollInterval = sysProps["pollInterval"]; 70 71 if (sysProps.contains("MinPowerSupplies")) 72 { 73 p.minPowerSupplies = sysProps["MinPowerSupplies"]; 74 } 75 else 76 { 77 p.minPowerSupplies = 0; 78 } 79 80 if (sysProps.contains("MaxPowerSupplies")) 81 { 82 p.maxPowerSupplies = sysProps["MaxPowerSupplies"]; 83 } 84 else 85 { 86 p.maxPowerSupplies = 0; 87 } 88 89 for (auto psuJSON : configFileJSON["PowerSupplies"]) 90 { 91 if (psuJSON.contains("Inventory") && psuJSON.contains("Bus") && 92 psuJSON.contains("Address")) 93 { 94 std::string invpath = psuJSON["Inventory"]; 95 std::uint8_t i2cbus = psuJSON["Bus"]; 96 std::string i2caddr = psuJSON["Address"]; 97 auto psu = 98 std::make_unique<PowerSupply>(bus, invpath, i2cbus, i2caddr); 99 psus.emplace_back(std::move(psu)); 100 } 101 else 102 { 103 log<level::ERR>("Insufficient PowerSupply properties"); 104 } 105 } 106 107 if (psus.empty()) 108 { 109 throw std::runtime_error("No power supplies to monitor"); 110 } 111 } 112 113 void PSUManager::powerStateChanged(sdbusplus::message::message& msg) 114 { 115 int32_t state = 0; 116 std::string msgSensor; 117 std::map<std::string, sdbusplus::message::variant<int32_t>> msgData; 118 msg.read(msgSensor, msgData); 119 120 // Check if it was the Present property that changed. 121 auto valPropMap = msgData.find("state"); 122 if (valPropMap != msgData.end()) 123 { 124 state = std::get<int32_t>(valPropMap->second); 125 126 // Power is on when state=1. Clear faults. 127 if (state) 128 { 129 powerOn = true; 130 clearFaults(); 131 } 132 else 133 { 134 powerOn = false; 135 } 136 } 137 } 138 139 } // namespace manager 140 } // namespace power 141 } // namespace phosphor 142