Update default floor action

Add action to be able to update the default fan floor thru a configured
event.

Tested:
    Default floor is updated based on state of group property value

Change-Id: I83a4ae313636abbe1e5c8b6ddfc2d5f9d281f844
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/actions.hpp b/control/actions.hpp
index f7053cb..c30945a 100644
--- a/control/actions.hpp
+++ b/control/actions.hpp
@@ -369,6 +369,53 @@
         int64_t upperBound,
         std::map<int64_t, uint64_t>&& valueToSpeed);
 
+/**
+ * @brief An action to update the default floor speed
+ * @details Provides the ability to update the default fan floor speed when
+ * all of the group members property values match the value given
+ *
+ * @param[in] state - State to compare the group's property value to
+ * @param[in] speed - Speed to set the default fan floor to
+ *
+ * @return Lambda function
+ *     A lambda function that checks all group members are at a specified state
+ * and updates the default fan floor speed.
+ */
+template <typename T>
+auto update_default_floor(T&& state, uint64_t speed)
+{
+    return [speed, state = std::forward<T>(state)](auto& zone, auto& group)
+    {
+        auto updateDefFloor = std::all_of(
+            group.begin(),
+            group.end(),
+            [&zone, &state](auto const& entry)
+            {
+                try
+                {
+                    return zone.template getPropertyValue<T>(
+                            std::get<pathPos>(entry),
+                            std::get<intfPos>(entry),
+                            std::get<propPos>(entry)) == state;
+                }
+                catch (const std::out_of_range& oore)
+                {
+                    // Default to property not equal when not found
+                    return false;
+                }
+            });
+
+        if (!updateDefFloor)
+        {
+            // Do not update the default floor
+            return;
+        }
+
+        // Set/update the default floor of the zone
+        zone.setDefFloor(speed);
+    };
+}
+
 } // namespace action
 } // namespace control
 } // namespace fan
diff --git a/control/example/events.yaml b/control/example/events.yaml
index 4c0e9be..ac33ca0 100644
--- a/control/example/events.yaml
+++ b/control/example/events.yaml
@@ -227,6 +227,12 @@
 #          - property
 #          - factor
 #          - delta
+#    - name: update_default_floor
+#      description: >
+#          Update the default fan floor to the given speed
+#      parameters:
+#          - property
+#          - speed
 #
 #events:
 #    - name: missing_before_high_speed
diff --git a/control/zone.hpp b/control/zone.hpp
index e48a981..6982508 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -300,6 +300,16 @@
         };
 
         /**
+         * @brief Set the default floor
+         *
+         * @param[in] speed - Speed to set the default floor to
+         */
+        inline void setDefFloor(uint64_t speed)
+        {
+            _defFloorSpeed = speed;
+        };
+
+        /**
          * @brief Get the ceiling speed
          *
          * @return - The current ceiling speed
@@ -637,7 +647,7 @@
         /**
          * The default floor speed for the zone
          */
-        const uint64_t _defFloorSpeed;
+        uint64_t _defFloorSpeed;
 
         /**
          * The default ceiling speed for the zone