Check initial event's group members' properties

On start of fan control, check the current event's group members'
property states and envoke the defined action function on the results.

Change-Id: I12509403328d90f85d67b393dbdd97d8710c83ef
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/zone.cpp b/control/zone.cpp
index 35c7d2b..13ee977 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -13,7 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include <phosphor-logging/elog.hpp>
 #include "zone.hpp"
+#include "utility.hpp"
 
 namespace phosphor
 {
@@ -22,6 +24,7 @@
 namespace control
 {
 
+using namespace phosphor::logging;
 
 Zone::Zone(Mode mode,
            sdbusplus::bus::bus& bus,
@@ -43,6 +46,27 @@
         // Setup signal trigger for set speed events
         for (auto& event : std::get<setSpeedEventsPos>(def))
         {
+            // Get the current value for each property
+            for (auto& entry : std::get<groupPos>(event))
+            {
+                try
+                {
+                    bool value = false;
+                    getProperty(_bus,
+                                entry.first,
+                                std::get<intfPos>(entry.second),
+                                std::get<propPos>(entry.second),
+                                value);
+                    setPropertyValue(entry.first.c_str(),
+                                     std::get<propPos>(entry.second).c_str(),
+                                     value);
+                }
+                catch (const std::exception& e)
+                {
+                    log<level::ERR>(e.what());
+                }
+            }
+            // Setup signal matches for property change events
             for (auto& prop : std::get<propChangeListPos>(event))
             {
                 _signalEvents.emplace_back(
@@ -60,6 +84,9 @@
                         signalHandler,
                         _signalEvents.back().get());
             }
+            // Run action function for initial event state
+            std::get<actionPos>(event)(*this,
+                                       std::get<groupPos>(event));
         }
     }
 }
@@ -90,6 +117,31 @@
     }
 }
 
+template <typename T>
+void Zone::getProperty(sdbusplus::bus::bus& bus,
+                       const std::string& path,
+                       const std::string& iface,
+                       const std::string& prop,
+                       T& value)
+{
+    sdbusplus::message::variant<T> property;
+    auto serv = phosphor::fan::util::getService(path, iface, bus);
+    auto hostCall = bus.new_method_call(serv.c_str(),
+                                        path.c_str(),
+                                        "org.freedesktop.DBus.Properties",
+                                        "Get");
+    hostCall.append(iface);
+    hostCall.append(prop);
+    auto hostResponseMsg = bus.call(hostCall);
+    if (hostResponseMsg.is_method_error())
+    {
+        throw std::runtime_error(
+            "Error in host call response for retrieving property");
+    }
+    hostResponseMsg.read(property);
+    value = sdbusplus::message::variant_ns::get<T>(property);
+}
+
 int Zone::signalHandler(sd_bus_message* msg,
                         void* data,
                         sd_bus_error* err)
diff --git a/control/zone.hpp b/control/zone.hpp
index b727567..c6e0594 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -154,6 +154,22 @@
         std::vector<sdbusplus::server::match::match> _matches;
 
         /**
+         * @brief Get a property value from the path/interface given
+         *
+         * @param[in] bus - the bus to use
+         * @param[in] path - the dbus path name
+         * @param[in] iface - the dbus interface name
+         * @param[in] prop - the property name
+         * @param[out] value - the value of the property
+         */
+        template <typename T>
+        static void getProperty(sdbusplus::bus::bus& bus,
+                                const std::string& path,
+                                const std::string& iface,
+                                const std::string& prop,
+                                T& value);
+
+        /**
          * @brief Dbus signal change handler
          *
          * @param[in] msg - Data associated with the subscribed signal