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(1000); 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("MinPowerSupplies")) 65 { 66 p.minPowerSupplies = sysProps["MinPowerSupplies"]; 67 } 68 else 69 { 70 p.minPowerSupplies = 0; 71 } 72 73 if (sysProps.contains("MaxPowerSupplies")) 74 { 75 p.maxPowerSupplies = sysProps["MaxPowerSupplies"]; 76 } 77 else 78 { 79 p.maxPowerSupplies = 0; 80 } 81 82 for (auto psuJSON : configFileJSON["PowerSupplies"]) 83 { 84 if (psuJSON.contains("Inventory") && psuJSON.contains("Bus") && 85 psuJSON.contains("Address")) 86 { 87 std::string invpath = psuJSON["Inventory"]; 88 std::uint8_t i2cbus = psuJSON["Bus"]; 89 std::string i2caddr = psuJSON["Address"]; 90 auto psu = 91 std::make_unique<PowerSupply>(bus, invpath, i2cbus, i2caddr); 92 psus.emplace_back(std::move(psu)); 93 } 94 else 95 { 96 log<level::ERR>("Insufficient PowerSupply properties"); 97 } 98 } 99 100 if (psus.empty()) 101 { 102 throw std::runtime_error("No power supplies to monitor"); 103 } 104 } 105 106 void PSUManager::powerStateChanged(sdbusplus::message::message& msg) 107 { 108 int32_t state = 0; 109 std::string msgSensor; 110 std::map<std::string, std::variant<int32_t>> msgData; 111 msg.read(msgSensor, msgData); 112 113 // Check if it was the Present property that changed. 114 auto valPropMap = msgData.find("state"); 115 if (valPropMap != msgData.end()) 116 { 117 state = std::get<int32_t>(valPropMap->second); 118 119 // Power is on when state=1. Clear faults. 120 if (state) 121 { 122 powerOn = true; 123 clearFaults(); 124 } 125 else 126 { 127 powerOn = false; 128 } 129 } 130 } 131 132 } // namespace manager 133 } // namespace power 134 } // namespace phosphor 135