1 #include "host_power.hpp" 2 3 #include <phosphor-logging/lg2.hpp> 4 #include <sdbusplus/async.hpp> 5 #include <sdbusplus/async/context.hpp> 6 #include <sdbusplus/async/match.hpp> 7 #include <sdbusplus/async/proxy.hpp> 8 #include <sdbusplus/bus/match.hpp> 9 #include <sdbusplus/message/native_types.hpp> 10 #include <xyz/openbmc_project/ObjectMapper/client.hpp> 11 #include <xyz/openbmc_project/State/Host/client.hpp> 12 13 PHOSPHOR_LOG2_USING; 14 15 using namespace std::literals; 16 17 namespace RulesIntf = sdbusplus::bus::match::rules; 18 19 using StateIntf = 20 sdbusplus::client::xyz::openbmc_project::state::Host<void, void>; 21 22 const auto transitionOn = 23 sdbusplus::client::xyz::openbmc_project::state::Host<>::Transition::On; 24 const auto transitionOff = 25 sdbusplus::client::xyz::openbmc_project::state::Host<>::Transition::Off; 26 27 namespace phosphor::software::host_power 28 { 29 30 const auto host0ObjectPath = sdbusplus::client::xyz::openbmc_project::state:: 31 Host<>::namespace_path::value + 32 std::string("/host0"); 33 34 constexpr const char* service = "xyz.openbmc_project.State.Host"; 35 36 HostPower::HostPower(sdbusplus::async::context& ctx) : 37 stateChangedMatch(ctx, RulesIntf::propertiesChanged(host0ObjectPath, 38 StateIntf::interface)) 39 {} 40 41 sdbusplus::async::task<bool> HostPower::setState(sdbusplus::async::context& ctx, 42 HostState state) 43 { 44 if (state != stateOn && state != stateOff) 45 { 46 error("Invalid power state {STATE}", "STATE", state); 47 co_return false; 48 } 49 50 auto client = sdbusplus::client::xyz::openbmc_project::state::Host(ctx) 51 .service(service) 52 .path(host0ObjectPath); 53 54 co_await client.requested_host_transition( 55 (state == stateOn) ? transitionOn : transitionOff); 56 57 debug("Requested host transition to {STATE}", "STATE", state); 58 59 constexpr size_t retries = 4; 60 constexpr size_t retryTimeout = 3; 61 62 for (size_t i = 0; i < retries; i++) 63 { 64 co_await sdbusplus::async::sleep_for( 65 ctx, std::chrono::seconds(retryTimeout)); 66 67 if ((co_await client.current_host_state()) == state) 68 { 69 debug("Successfully achieved state {STATE}", "STATE", state); 70 co_return true; 71 } 72 } 73 74 error("Failed to achieve state {STATE} before the timeout of {TIMEOUT}s", 75 "STATE", state, "TIMEOUT", retries * retryTimeout); 76 77 co_return false; 78 } 79 80 sdbusplus::async::task<HostState> HostPower::getState( 81 sdbusplus::async::context& ctx) 82 { 83 auto client = sdbusplus::client::xyz::openbmc_project::state::Host(ctx) 84 .service(service) 85 .path(host0ObjectPath); 86 87 auto res = co_await client.current_host_state(); 88 89 if (res != stateOn && res != stateOff) 90 { 91 error("Unexpected power state: {STATE}", "STATE", res); 92 } 93 94 co_return res; 95 } 96 97 } // namespace phosphor::software::host_power 98