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 // NOLINTBEGIN(readability-static-accessed-through-instance) 42 sdbusplus::async::task<bool> HostPower::setState(sdbusplus::async::context& ctx, 43 HostState state) 44 // NOLINTEND(readability-static-accessed-through-instance) 45 { 46 if (state != stateOn && state != stateOff) 47 { 48 error("Invalid power state {STATE}", "STATE", state); 49 co_return false; 50 } 51 52 auto client = sdbusplus::client::xyz::openbmc_project::state::Host(ctx) 53 .service(service) 54 .path(host0ObjectPath); 55 56 co_await client.requested_host_transition( 57 (state == stateOn) ? transitionOn : transitionOff); 58 59 debug("Requested host transition to {STATE}", "STATE", state); 60 61 constexpr size_t retries = 4; 62 constexpr size_t retryTimeout = 3; 63 64 for (size_t i = 0; i < retries; i++) 65 { 66 co_await sdbusplus::async::sleep_for( 67 ctx, std::chrono::seconds(retryTimeout)); 68 69 if ((co_await client.current_host_state()) == state) 70 { 71 debug("Successfully achieved state {STATE}", "STATE", state); 72 co_return true; 73 } 74 } 75 76 error("Failed to achieve state {STATE} before the timeout of {TIMEOUT}s", 77 "STATE", state, "TIMEOUT", retries * retryTimeout); 78 79 co_return false; 80 } 81 82 // NOLINTBEGIN(readability-static-accessed-through-instance) 83 sdbusplus::async::task<HostState> HostPower::getState( 84 sdbusplus::async::context& ctx) 85 // NOLINTEND(readability-static-accessed-through-instance) 86 { 87 auto client = sdbusplus::client::xyz::openbmc_project::state::Host(ctx) 88 .service(service) 89 .path(host0ObjectPath); 90 91 auto res = co_await client.current_host_state(); 92 93 if (res != stateOn && res != stateOff) 94 { 95 error("Unexpected power state: {STATE}", "STATE", res); 96 } 97 98 co_return res; 99 } 100 101 } // namespace phosphor::software::host_power 102