diff options
Diffstat (limited to 'control')
-rw-r--r-- | control/actions.hpp | 109 | ||||
-rw-r--r-- | control/zone.cpp | 8 | ||||
-rw-r--r-- | control/zone.hpp | 50 |
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; |