Use systemd target states to track chassis on/off states

Change-Id: Id76074cc500fa8d147d3d219af62f8d224881b18
Signed-off-by: Andrew Geissler <andrewg@us.ibm.com>
diff --git a/chassis_state_manager.cpp b/chassis_state_manager.cpp
index fb0c2a3..d7549a5 100644
--- a/chassis_state_manager.cpp
+++ b/chassis_state_manager.cpp
@@ -1,3 +1,4 @@
+#include <sdbusplus/bus.hpp>
 #include <log.hpp>
 #include "chassis_state_manager.hpp"
 
@@ -13,40 +14,29 @@
 
 using namespace phosphor::logging;
 
+constexpr auto CHASSIS_STATE_POWEROFF_TGT = "obmc-power-chassis-off@0.target";
+constexpr auto CHASSIS_STATE_POWERON_TGT = "obmc-power-chassis-on@0.target";
+
 /* Map a transition to it's systemd target */
 const std::map<server::Chassis::Transition,std::string> SYSTEMD_TARGET_TABLE =
 {
-        {server::Chassis::Transition::Off, "obmc-power-chassis-off@0.target"},
-        {server::Chassis::Transition::On, "obmc-power-chassis-on@0.target"}
+        {server::Chassis::Transition::Off, CHASSIS_STATE_POWEROFF_TGT},
+        {server::Chassis::Transition::On, CHASSIS_STATE_POWERON_TGT}
 };
 
 constexpr auto SYSTEMD_SERVICE   = "org.freedesktop.systemd1";
 constexpr auto SYSTEMD_OBJ_PATH  = "/org/freedesktop/systemd1";
 constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
 
-/* TODO:Issue 774 - Use systemd target signals to control chassis state */
-int Chassis::handlePgoodOn(sd_bus_message* /*msg*/, void* usrData,
-                           sd_bus_error* retError)
+void Chassis::subscribeToSystemdSignals()
 {
-    log<level::INFO>("Pgood has turned on",
-                     entry("CHASSIS_CURRENT_POWER_STATE=%s",
-                           convertForMessage(PowerState::On).c_str()));
-    auto chassisInst = static_cast<Chassis*>(usrData);
-    chassisInst->currentPowerState(PowerState::On);
+    auto method = this->bus.new_method_call(SYSTEMD_SERVICE,
+                                            SYSTEMD_OBJ_PATH,
+                                            SYSTEMD_INTERFACE,
+                                            "Subscribe");
+    this->bus.call_noreply(method);
 
-    return 0;
-}
-
-int Chassis::handlePgoodOff(sd_bus_message* /*msg*/, void* usrData,
-                           sd_bus_error* retError)
-{
-    log<level::INFO>("Pgood has turned off",
-                     entry("CHASSIS_CURRENT_POWER_STATE=%s",
-                           convertForMessage(PowerState::Off).c_str()));
-    auto chassisInst = static_cast<Chassis*>(usrData);
-    chassisInst->currentPowerState(PowerState::Off);
-
-    return 0;
+    return;
 }
 
 // TODO - Will be rewritten once sdbusplus client bindings are in place
@@ -101,6 +91,40 @@
     return;
 }
 
+int Chassis::sysStateChangeSignal(sd_bus_message *msg, void *userData,
+                                  sd_bus_error *retError)
+{
+    return static_cast<Chassis*>(userData)->sysStateChange(msg, retError);
+}
+
+int Chassis::sysStateChange(sd_bus_message* msg,
+                            sd_bus_error* retError)
+{
+    uint32_t newStateID {};
+    sdbusplus::message::object_path newStateObjPath;
+    std::string newStateUnit{};
+    std::string newStateResult{};
+
+    auto sdPlusMsg = sdbusplus::message::message(msg);
+    //Read the msg and populate each variable
+    sdPlusMsg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);
+
+    if((newStateUnit == CHASSIS_STATE_POWEROFF_TGT) &&
+       (newStateResult == "done"))
+    {
+        log<level::INFO>("Recieved signal that power OFF is complete");
+        this->currentPowerState(server::Chassis::PowerState::Off);
+    }
+    else if((newStateUnit == CHASSIS_STATE_POWERON_TGT) &&
+            (newStateResult == "done"))
+     {
+         log<level::INFO>("Recieved signal that power ON is complete");
+         this->currentPowerState(server::Chassis::PowerState::On);
+     }
+
+    return 0;
+}
+
 Chassis::Transition Chassis::requestedPowerTransition(Transition value)
 {
 
diff --git a/chassis_state_manager.hpp b/chassis_state_manager.hpp
index 181d75c..a56924e 100644
--- a/chassis_state_manager.hpp
+++ b/chassis_state_manager.hpp
@@ -36,24 +36,22 @@
                     sdbusplus::xyz::openbmc_project::State::server::Chassis>(
                             bus, objPath, true),
                 bus(bus),
-                pgoodOn(bus,
-                        "type='signal',member='PowerGood'",
-                        Chassis::handlePgoodOn,
-                        this),
-                pgoodOff(bus,
-                        "type='signal',member='PowerLost'",
-                        Chassis::handlePgoodOff,
-                        this)
+                systemdSignals(bus,
+                               "type='signal',"
+                               "member='JobRemoved',"
+                               "path='/org/freedesktop/systemd1',"
+                               "interface='org.freedesktop.systemd1.Manager'",
+                                sysStateChangeSignal,
+                                this)
         {
+            subscribeToSystemdSignals();
+
             determineInitialState();
 
             // We deferred this until we could get our property correct
             this->emit_object_added();
         }
 
-        /** @brief Determine initial chassis state and set internally */
-        void determineInitialState();
-
         /** @brief Set value of RequestedPowerTransition */
         Transition requestedPowerTransition(Transition value) override;
 
@@ -61,6 +59,18 @@
         PowerState currentPowerState(PowerState value) override;
 
     private:
+        /** @brief Determine initial chassis state and set internally */
+        void determineInitialState();
+
+        /**
+         * @brief subscribe to the systemd signals
+         *
+         * This object needs to capture when it's systemd targets complete
+         * so it can keep it's state updated
+         *
+         **/
+        void subscribeToSystemdSignals();
+
         /** @brief Execute the transition request
          *
          * This function calls the appropriate systemd target for the input
@@ -70,40 +80,36 @@
          */
         void executeTransition(Transition tranReq);
 
-        /** @brief Callback function for pgood going to on state
+        /** @brief Callback function on systemd state changes
          *
-         *  Update chassis object state to reflect pgood going to on state
+         * Will just do a call into the appropriate object for processing
          *
-         * @param[in] msg        - Data associated with subscribed signal
-         * @param[in] userData   - Pointer to this object instance
-         * @param[in] retError   - Return error data
+         * @param[in]  msg       - Data associated with subscribed signal
+         * @param[in]  userData  - Pointer to this object instance
+         * @param[out] retError  - Not used but required with signal API
          *
          */
-        static int handlePgoodOn(sd_bus_message* msg,
-                                 void* userData,
-                                 sd_bus_error* retError);
+        static int sysStateChangeSignal(sd_bus_message* msg,
+                                        void* userData,
+                                        sd_bus_error* retError);
 
-        /** @brief Callback function for pgood going to off state
+        /** @brief Check if systemd state change is relevant to this object
          *
-         *  Update chassis object state to reflect pgood going to off state
+         * Instance specific interface to handle the detected systemd state
+         * change
          *
-         * @param[in] msg        - Data associated with subscribed signal
-         * @param[in] userData   - Pointer to this object instance
-         * @param[in] retError   - Return error data
+         * @param[in]  msg       - Data associated with subscribed signal
+         * @param[out] retError  - Not used but required with signal API
          *
          */
-        static int handlePgoodOff(sd_bus_message* msg,
-                                  void* userData,
-                                  sd_bus_error* retError);
+        int sysStateChange(sd_bus_message* msg,
+                           sd_bus_error* retError);
 
         /** @brief Persistent sdbusplus DBus connection. */
         sdbusplus::bus::bus& bus;
 
-        /** @brief Used to subscribe to dbus pgood on state changes */
-        sdbusplus::server::match::match pgoodOn;
-
-        /** @brief Used to subscribe to dbus pgood off state changes */
-        sdbusplus::server::match::match pgoodOff;
+        /** @brief Used to subscribe to dbus systemd signals **/
+        sdbusplus::server::match::match systemdSignals;
 };
 
 } // namespace manager