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