summaryrefslogtreecommitdiffstats
path: root/control
diff options
context:
space:
mode:
Diffstat (limited to 'control')
-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