summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barth <msbarth@us.ibm.com>2017-06-13 16:29:09 -0500
committerPatrick Williams <patrick@stwcx.xyz>2017-06-28 15:59:11 +0000
commite0ca13eb5b2feba044505e3234c8381d3ab03187 (patch)
tree01002dfa5a34d991477e3f3347b8c1e05457c5e8
parent618027abcf491b0b58f71bfe2b48c55dfb86462e (diff)
downloadphosphor-fan-presence-e0ca13eb5b2feba044505e3234c8381d3ab03187.tar.gz
phosphor-fan-presence-e0ca13eb5b2feba044505e3234c8381d3ab03187.zip
Enable setting/adjusting fan ceiling speed
Set the default ceiling to be what's given as full speed and adjust the ceiling speed based on an average of a given set of sensor values. The ceiling is chosen from a given map's key transition values. The map consists of key, value pairs where each key is the sensor value transition point and the value is the ceiling speed for when that transition occurs. The previous key value is needed to determine the direction in which to chose the appropriate ceiling speed allowing a buffer zone between ceiling changes if defined to. Resolves openbmc/openbmc#1628 Change-Id: I7c9c553b5d0c3219c51b563aec7dd5d5f090916b Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
-rw-r--r--control/actions.hpp109
-rw-r--r--control/zone.cpp8
-rw-r--r--control/zone.hpp50
3 files changed, 166 insertions, 1 deletions
diff --git a/control/actions.hpp b/control/actions.hpp
index a99fa97..4393c4d 100644
--- a/control/actions.hpp
+++ b/control/actions.hpp
@@ -100,6 +100,115 @@ auto set_floor_from_average_sensor_value(
};
}
+/**
+ * @brief An action to set the ceiling speed on a zone
+ * @details Based on the average of the defined sensor group values, the ceiling
+ * speed is selected from the map key transition point that the average sensor
+ * value falls within depending on the key values direction from what was
+ * previously read.
+ *
+ * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions
+ *
+ * @return Lambda function
+ * A lambda function to set the zone's ceiling speed when the average of
+ * property values within the group is above(increasing) or
+ * below(decreasing) the key transition point
+ */
+auto set_ceiling_from_average_sensor_value(
+ std::map<int64_t, uint64_t>&& val_to_speed)
+{
+ return [val_to_speed = std::move(val_to_speed)](auto& zone, auto& group)
+ {
+ auto speed = zone.getCeiling();
+ if (group.size() != 0)
+ {
+ auto sumValue = std::accumulate(
+ group.begin(),
+ group.end(),
+ 0,
+ [&zone](int64_t sum, auto const& entry)
+ {
+ return sum + zone.template getPropertyValue<int64_t>(
+ entry.first,
+ std::get<intfPos>(entry.second),
+ std::get<propPos>(entry.second));
+ });
+ auto avgValue = sumValue / group.size();
+ auto prevValue = zone.swapCeilingKeyValue(avgValue);
+ if (avgValue != prevValue)
+ {// Only check if previous and new values differ
+ if (avgValue < prevValue)
+ {// Value is decreasing from previous
+ for (auto it = val_to_speed.rbegin();
+ it != val_to_speed.rend();
+ ++it)
+ {
+ if (it == val_to_speed.rbegin() &&
+ avgValue >= it->first)
+ {
+ // Value is at/above last map key,
+ // set ceiling speed to the last map key's value
+ speed = it->second;
+ break;
+ }
+ else if (std::next(it, 1) == val_to_speed.rend() &&
+ avgValue <= it->first)
+ {
+ // Value is at/below first map key,
+ // set ceiling speed to the first map key's value
+ speed = it->second;
+ break;
+ }
+ if (avgValue < it->first &&
+ it->first <= prevValue)
+ {
+ // Value decreased & transitioned across a map key,
+ // update ceiling speed to this map key's value
+ // when new value is below map's key and the key
+ // is at/below the previous value
+ speed = it->second;
+ }
+ }
+ }
+ else
+ {// Value is increasing from previous
+ for (auto it = val_to_speed.begin();
+ it != val_to_speed.end();
+ ++it)
+ {
+ if (it == val_to_speed.begin() &&
+ avgValue <= it->first)
+ {
+ // Value is at/below first map key,
+ // set ceiling speed to the first map key's value
+ speed = it->second;
+ break;
+ }
+ else if (std::next(it, 1) == val_to_speed.end() &&
+ avgValue >= it->first)
+ {
+ // Value is at/above last map key,
+ // set ceiling speed to the last map key's value
+ speed = it->second;
+ break;
+ }
+ if (avgValue > it->first &&
+ it->first >= prevValue)
+ {
+ // Value increased & transitioned across a map key,
+ // update ceiling speed to this map key's value
+ // when new value is above map's key and the key
+ // is at/above the previous value
+ speed = it->second;
+ }
+ }
+ }
+ }
+ }
+ zone.setCeiling(speed);
+ };
+}
+
} // namespace action
} // namespace control
} // namespace fan
diff --git a/control/zone.cpp b/control/zone.cpp
index 67e22d9..d569aa8 100644
--- a/control/zone.cpp
+++ b/control/zone.cpp
@@ -37,7 +37,8 @@ Zone::Zone(Mode mode,
_bus(bus),
_fullSpeed(std::get<fullSpeedPos>(def)),
_zoneNum(std::get<zoneNumPos>(def)),
- _defFloorSpeed(std::get<floorSpeedPos>(def))
+ _defFloorSpeed(std::get<floorSpeedPos>(def)),
+ _defCeilingSpeed(std::get<fullSpeedPos>(def))
{
auto& fanDefs = std::get<fanListPos>(def);
@@ -109,6 +110,11 @@ void Zone::setSpeed(uint64_t speed)
{
speed = _floorSpeed;
}
+ //TODO openbmc/openbmc#1626 Move to control algorithm function
+ if (speed > _ceilingSpeed)
+ {
+ speed = _ceilingSpeed;
+ }
fan->setSpeed(speed);
}
}
diff --git a/control/zone.hpp b/control/zone.hpp
index 24739f8..fef3734 100644
--- a/control/zone.hpp
+++ b/control/zone.hpp
@@ -1,5 +1,6 @@
#pragma once
#include <vector>
+#include <algorithm>
#include <sdbusplus/bus.hpp>
#include <sdbusplus/server.hpp>
#include "fan.hpp"
@@ -133,6 +134,40 @@ class Zone
_floorSpeed = speed;
};
+ /**
+ * @brief Get the ceiling speed
+ *
+ * @return - The current ceiling speed
+ */
+ inline auto& getCeiling() const
+ {
+ return _ceilingSpeed;
+ };
+
+ /**
+ * @brief Set the ceiling speed to the given speed
+ *
+ * @param[in] speed - Speed to set the ceiling to
+ */
+ inline void setCeiling(uint64_t speed)
+ {
+ _ceilingSpeed = speed;
+ };
+
+ /**
+ * @brief Swaps the ceiling key value with what's given and
+ * returns the value that was swapped.
+ *
+ * @param[in] keyValue - New ceiling key value
+ *
+ * @return - Ceiling key value prior to swapping
+ */
+ inline auto swapCeilingKeyValue(int64_t keyValue)
+ {
+ std::swap(_ceilingKeyValue, keyValue);
+ return keyValue;
+ };
+
private:
/**
@@ -156,11 +191,26 @@ class Zone
const uint64_t _defFloorSpeed;
/**
+ * The default ceiling speed for the zone
+ */
+ const uint64_t _defCeilingSpeed;
+
+ /**
* The floor speed to not go below
*/
uint64_t _floorSpeed = _defFloorSpeed;
/**
+ * The ceiling speed to not go above
+ */
+ uint64_t _ceilingSpeed = _defCeilingSpeed;
+
+ /**
+ * The previous sensor value for calculating the ceiling
+ */
+ int64_t _ceilingKeyValue = 0;
+
+ /**
* Automatic fan control active state
*/
bool _isActive = true;
OpenPOWER on IntegriCloud