control: Introduce `poweron_target` configuration attribute

Use a required `poweron_target` attribute to eventually replace
`full_speed` instead of using `default_ceiling`. This allows a different
target other than the default ceiling to be used at poweron. In
addition, the `default_ceiling` and `default_floor` attributes can be
made optional. A user that just wants to set fans to a speed and not
change them does not need to provide a default ceiling or floor. The
default ceiling will now default to the poweron target value, if not
given, and the default floor will now default to 0 when not given.

Change-Id: I232935c00c34086ebb286adc4f9b91f5e302e64f
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/control/json/zone.cpp b/control/json/zone.cpp
index 434931a..45157ae 100644
--- a/control/json/zone.cpp
+++ b/control/json/zone.cpp
@@ -48,9 +48,10 @@
           {DBusZone::currentProp, zone::property::current}}}};
 
 Zone::Zone(const json& jsonObj, const sdeventplus::Event& event, Manager* mgr) :
-    ConfigBase(jsonObj), _dbusZone{}, _manager(mgr), _incDelay(0), _floor(0),
-    _target(0), _incDelta(0), _decDelta(0), _requestTargetBase(0),
-    _isActive(true), _incTimer(event, std::bind(&Zone::incTimerExpired, this)),
+    ConfigBase(jsonObj), _dbusZone{}, _manager(mgr), _defaultFloor(0),
+    _incDelay(0), _floor(0), _target(0), _incDelta(0), _decDelta(0),
+    _requestTargetBase(0), _isActive(true),
+    _incTimer(event, std::bind(&Zone::incTimerExpired, this)),
     _decTimer(event, std::bind(&Zone::decTimerExpired, this))
 {
     // Increase delay is optional, defaults to 0
@@ -59,9 +60,29 @@
         _incDelay =
             std::chrono::seconds(jsonObj["increase_delay"].get<uint64_t>());
     }
-    setDefaultCeiling(jsonObj);
-    setDefaultFloor(jsonObj);
+
+    // Poweron target is required
+    setPowerOnTarget(jsonObj);
+
+    // Default ceiling is optional, defaults to poweron target
+    _defaultCeiling = _poweronTarget;
+    if (jsonObj.contains("default_ceiling"))
+    {
+        _defaultCeiling = jsonObj["default_ceiling"].get<uint64_t>();
+    }
+    // Start with the current ceiling set as the default ceiling
+    _ceiling = _defaultCeiling;
+
+    // Default floor is optional, defaults to 0
+    if (jsonObj.contains("default_floor"))
+    {
+        _defaultFloor = jsonObj["default_floor"].get<uint64_t>();
+        // Start with the current floor set as the default
+        _floor = _defaultFloor;
+    }
+
     setDecInterval(jsonObj);
+
     // Setting properties on interfaces to be served are optional
     if (jsonObj.contains("interfaces"))
     {
@@ -234,40 +255,25 @@
                        [&prop](const auto& p) { return prop == p; });
 }
 
-void Zone::setDefaultCeiling(const json& jsonObj)
+void Zone::setPowerOnTarget(const json& jsonObj)
 {
-    // TODO Remove "full_speed" after configs replaced with "default_ceiling"
-    if (!jsonObj.contains("full_speed") && !jsonObj.contains("default_ceiling"))
+    // TODO Remove "full_speed" after configs replaced with "poweron_target"
+    if (!jsonObj.contains("full_speed") && !jsonObj.contains("poweron_target"))
     {
-        log<level::ERR>("Missing required zone's default ceiling",
-                        entry("JSON=%s", jsonObj.dump().c_str()));
-        throw std::runtime_error("Missing required zone's default ceiling");
+        auto msg = "Missing required zone's poweron target";
+        log<level::ERR>(msg, entry("JSON=%s", jsonObj.dump().c_str()));
+        throw std::runtime_error(msg);
     }
     if (jsonObj.contains("full_speed"))
     {
-        _defaultCeiling = jsonObj["full_speed"].get<uint64_t>();
+        _poweronTarget = jsonObj["full_speed"].get<uint64_t>();
     }
     else
     {
-        _defaultCeiling = jsonObj["default_ceiling"].get<uint64_t>();
+        _poweronTarget = jsonObj["poweron_target"].get<uint64_t>();
     }
-    // Start with the current target set as the default
-    _target = _defaultCeiling;
-    // Start with the current ceiling set as the default
-    _ceiling = _defaultCeiling;
-}
-
-void Zone::setDefaultFloor(const json& jsonObj)
-{
-    if (!jsonObj.contains("default_floor"))
-    {
-        log<level::ERR>("Missing required zone's default floor",
-                        entry("JSON=%s", jsonObj.dump().c_str()));
-        throw std::runtime_error("Missing required zone's default floor");
-    }
-    _defaultFloor = jsonObj["default_floor"].get<uint64_t>();
-    // Start with the current floor set as the default
-    _floor = _defaultFloor;
+    // Start with the current target set as the poweron target
+    _target = _poweronTarget;
 }
 
 void Zone::setDecInterval(const json& jsonObj)
@@ -353,7 +359,8 @@
 
 /**
  * Properties of interfaces supported by the zone configuration that return
- * a handler function that sets the zone's property value(s) and persist state.
+ * a handler function that sets the zone's property value(s) and persist
+ * state.
  */
 namespace zone::property
 {
@@ -365,9 +372,9 @@
     std::vector<std::string> values;
     if (!jsonObj.contains("values"))
     {
-        log<level::ERR>(
-            "No 'values' found for \"Supported\" property, using an empty list",
-            entry("JSON=%s", jsonObj.dump().c_str()));
+        log<level::ERR>("No 'values' found for \"Supported\" property, "
+                        "using an empty list",
+                        entry("JSON=%s", jsonObj.dump().c_str()));
     }
     else
     {
@@ -391,8 +398,8 @@
         &DBusZone::supported, std::move(values), persist);
 }
 
-// Get a set property handler function for a configured value of the "Current"
-// property
+// Get a set property handler function for a configured value of the
+// "Current" property
 std::function<void(DBusZone&, Zone&)> current(const json& jsonObj, bool persist)
 {
     // Use default value for "Current" property if no "value" entry given
diff --git a/control/json/zone.hpp b/control/json/zone.hpp
index c4d90d7..50d8718 100644
--- a/control/json/zone.hpp
+++ b/control/json/zone.hpp
@@ -357,6 +357,9 @@
     /* The zone's manager */
     Manager* _manager;
 
+    /* The zone's poweron target value for fans */
+    uint64_t _poweronTarget;
+
     /* The zone's default ceiling value for fans */
     uint64_t _defaultCeiling;
 
@@ -423,24 +426,14 @@
     std::vector<std::function<void(DBusZone&, Zone&)>> _propInitFunctions;
 
     /**
-     * @brief Parse and set the zone's default ceiling value
+     * @brief Parse and set the zone's poweron target value
      *
      * @param[in] jsonObj - JSON object for the zone
      *
-     * Sets the default ceiling value for the zone from the JSON configuration
+     * Sets the poweron target value for the zone from the JSON configuration
      * object
      */
-    void setDefaultCeiling(const json& jsonObj);
-
-    /**
-     * @brief Parse and set the zone's default floor value
-     *
-     * @param[in] jsonObj - JSON object for the zone
-     *
-     * Sets the default floor value for the zone from the JSON configuration
-     * object
-     */
-    void setDefaultFloor(const json& jsonObj);
+    void setPowerOnTarget(const json& jsonObj);
 
     /**
      * @brief Parse and set the zone's decrease interval(in seconds)