From b280bfa4286c708b4bb65d82e3b41cc883b279f0 Mon Sep 17 00:00:00 2001 From: Matthew Barth Date: Fri, 15 Sep 2017 09:56:50 -0500 Subject: Create set request speed base action function This action function is intended to allow the base request speed to be set to the max value from a group of properties. The base request speed is the base speed used in requesting a new target speed. By default, the base request speed is the current target speed. For example, this action can be used to set the base request speed used in calculating a new target speed to be based on the max tach feedback speed from a group of fans instead of the current target speed. Adding this action function requires the other non-template functions to also be slightly modified due to linker errors. Change-Id: Ibbe9b33678b10cb49466174088a587b27bf56d62 Signed-off-by: Matthew Barth --- control/Makefile.am | 1 + control/actions.cpp | 207 ++++++++++++++++++++++++++++++++++++++++++++++++++++ control/actions.hpp | 193 +++++++----------------------------------------- 3 files changed, 235 insertions(+), 166 deletions(-) create mode 100644 control/actions.cpp diff --git a/control/Makefile.am b/control/Makefile.am index 7a970ea..09fb1a2 100644 --- a/control/Makefile.am +++ b/control/Makefile.am @@ -9,6 +9,7 @@ phosphor_fan_control_SOURCES = \ fan.cpp \ main.cpp \ manager.cpp \ + actions.cpp \ zone.cpp nodist_phosphor_fan_control_SOURCES = \ diff --git a/control/actions.cpp b/control/actions.cpp new file mode 100644 index 0000000..a608293 --- /dev/null +++ b/control/actions.cpp @@ -0,0 +1,207 @@ +#include "actions.hpp" + +namespace phosphor +{ +namespace fan +{ +namespace control +{ +namespace action +{ + +using namespace phosphor::fan; + +void set_request_speed_base_with_max(control::Zone& zone, + const Group& group) +{ + int64_t base = 0; + std::for_each( + group.begin(), + group.end(), + [&zone, &base](auto const& entry) + { + try + { + auto value = zone.template getPropertyValue( + entry.first, + std::get(entry.second), + std::get(entry.second)); + base = std::max(base, value); + } + catch (const std::out_of_range& oore) + { + // Property value not found, base request speed unchanged + } + }); + // A request speed base of 0 defaults to the current target speed + zone.setRequestSpeedBase(base); +} + +Action set_floor_from_average_sensor_value( + std::map&& val_to_speed) +{ + return [val_to_speed = std::move(val_to_speed)](control::Zone& zone, + const Group& group) + { + auto speed = zone.getDefFloor(); + if (group.size() != 0) + { + auto count = 0; + auto sumValue = std::accumulate( + group.begin(), + group.end(), + 0, + [&zone, &count](int64_t sum, auto const& entry) + { + try + { + return sum + + zone.template getPropertyValue( + entry.first, + std::get(entry.second), + std::get(entry.second)); + } + catch (const std::out_of_range& oore) + { + count++; + return sum; + } + }); + if ((group.size() - count) > 0) + { + auto groupSize = static_cast(group.size()); + auto avgValue = sumValue / (groupSize - count); + auto it = std::find_if( + val_to_speed.begin(), + val_to_speed.end(), + [&avgValue](auto const& entry) + { + return avgValue < entry.first; + } + ); + if (it != std::end(val_to_speed)) + { + speed = (*it).second; + } + } + } + zone.setFloor(speed); + }; +} + +Action set_ceiling_from_average_sensor_value( + std::map&& val_to_speed) +{ + return [val_to_speed = std::move(val_to_speed)](Zone& zone, + const Group& group) + { + auto speed = zone.getCeiling(); + if (group.size() != 0) + { + auto count = 0; + auto sumValue = std::accumulate( + group.begin(), + group.end(), + 0, + [&zone, &count](int64_t sum, auto const& entry) + { + try + { + return sum + + zone.template getPropertyValue( + entry.first, + std::get(entry.second), + std::get(entry.second)); + } + catch (const std::out_of_range& oore) + { + count++; + return sum; + } + }); + if ((group.size() - count) > 0) + { + auto groupSize = static_cast(group.size()); + auto avgValue = sumValue / (groupSize - count); + 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 +} // namespace phosphor diff --git a/control/actions.hpp b/control/actions.hpp index ecf900e..3061814 100644 --- a/control/actions.hpp +++ b/control/actions.hpp @@ -2,6 +2,8 @@ #include #include +#include "types.hpp" +#include "zone.hpp" namespace phosphor { @@ -12,6 +14,19 @@ namespace control namespace action { +/** + * @brief An action to set the request speed base + * @details A new target speed is determined using a speed delta being added + * or subtracted, for increases or decrease respectively, from a base speed. + * This base speed defaults to be the current target speed or is set to a + * different base speed(i.e. the fans' tach feedback speed) to request a new + * target from. + * + * @param[in] zone - Zone containing fans + * @param[in] group - Group of sensors to determine base from + */ +void set_request_speed_base_with_max(Zone& zone, const Group& group); + /** * @brief An action to set the speed on a zone * @details The zone is held at the given speed when a defined number of @@ -67,183 +82,29 @@ auto count_state_before_speed(size_t count, T&& state, uint64_t speed) * * @param[in] val_to_speed - Ordered map of sensor value-to-speed * - * @return Lambda function - * A lambda function to set the zone's floor speed when the average of + * @return Action lambda function + * An Action function to set the zone's floor speed when the average of * property values within the group is below the lowest sensor value given */ -auto set_floor_from_average_sensor_value( - std::map&& val_to_speed) -{ - return [val_to_speed = std::move(val_to_speed)](auto& zone, auto& group) - { - auto speed = zone.getDefFloor(); - if (group.size() != 0) - { - auto count = 0; - auto sumValue = std::accumulate( - group.begin(), - group.end(), - 0, - [&zone, &count](int64_t sum, auto const& entry) - { - try - { - return sum + - zone.template getPropertyValue( - entry.first, - std::get(entry.second), - std::get(entry.second)); - } - catch (const std::out_of_range& oore) - { - count++; - return sum; - } - }); - if ((group.size() - count) > 0) - { - auto avgValue = sumValue / (group.size() - count); - auto it = std::find_if( - val_to_speed.begin(), - val_to_speed.end(), - [&avgValue](auto const& entry) - { - return avgValue < entry.first; - } - ); - if (it != std::end(val_to_speed)) - { - speed = (*it).second; - } - } - } - zone.setFloor(speed); - }; -} +Action set_floor_from_average_sensor_value( + std::map&& val_to_speed); /** * @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. + * @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 + * @return Action lambda function + * An Action 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&& 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 count = 0; - auto sumValue = std::accumulate( - group.begin(), - group.end(), - 0, - [&zone, &count](int64_t sum, auto const& entry) - { - try - { - return sum + - zone.template getPropertyValue( - entry.first, - std::get(entry.second), - std::get(entry.second)); - } - catch (const std::out_of_range& oore) - { - count++; - return sum; - } - }); - if ((group.size() - count) > 0) - { - auto avgValue = sumValue / (group.size() - count); - 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); - }; -} +Action set_ceiling_from_average_sensor_value( + std::map&& val_to_speed); /** * @brief An action to set the speed increase delta and request speed change -- cgit v1.2.1