117d1fe23SMatthew Barth #pragma once
217d1fe23SMatthew Barth
33e1bb274SMatthew Barth #include "types.hpp"
43e1bb274SMatthew Barth #include "utility.hpp"
53e1bb274SMatthew Barth #include "zone.hpp"
63e1bb274SMatthew Barth
717d1fe23SMatthew Barth #include <algorithm>
84af419cdSMatthew Barth #include <numeric>
917d1fe23SMatthew Barth
1017d1fe23SMatthew Barth namespace phosphor
1117d1fe23SMatthew Barth {
1217d1fe23SMatthew Barth namespace fan
1317d1fe23SMatthew Barth {
1417d1fe23SMatthew Barth namespace control
1517d1fe23SMatthew Barth {
1617d1fe23SMatthew Barth namespace action
1717d1fe23SMatthew Barth {
1817d1fe23SMatthew Barth
1917d1fe23SMatthew Barth /**
202a646c5fSMatthew Barth * @brief An action that wraps a list of actions with a timer
212a646c5fSMatthew Barth * @details Sets up a list of actions to be invoked when the defined timer
222a646c5fSMatthew Barth * expires (or for each expiration of a repeating timer).
232a646c5fSMatthew Barth *
242a646c5fSMatthew Barth * @param[in] tConf - Timer configuration parameters
252a646c5fSMatthew Barth * @param[in] action - List of actions to be called when the timer expires
262a646c5fSMatthew Barth *
272a646c5fSMatthew Barth * @return Action lambda function
282a646c5fSMatthew Barth * An Action function that creates a timer
292a646c5fSMatthew Barth */
303e1bb274SMatthew Barth Action call_actions_based_on_timer(TimerConf&& tConf,
312a646c5fSMatthew Barth std::vector<Action>&& actions);
322a646c5fSMatthew Barth
332a646c5fSMatthew Barth /**
3498726c45SMatthew Barth * @brief An action that sets the floor to the default fan floor speed
3598726c45SMatthew Barth * @details Sets the fan floor to the defined default fan floor speed when a
3698726c45SMatthew Barth * service associated to the given group has terminated. Once all services
3798726c45SMatthew Barth * are functional and providing the sensors again, the fan floor is allowed
3898726c45SMatthew Barth * to be set normally.
3998726c45SMatthew Barth *
4098726c45SMatthew Barth * @param[in] zone - Zone containing fans
4198726c45SMatthew Barth * @param[in] group - Group of sensors to determine services' states
4298726c45SMatthew Barth */
4398726c45SMatthew Barth void default_floor_on_missing_owner(Zone& zone, const Group& group);
4498726c45SMatthew Barth
4598726c45SMatthew Barth /**
460decd1bdSMatthew Barth * @brief An action to set a speed when a service owner is missing
470decd1bdSMatthew Barth * @details Sets the fans to the given speed when any service owner associated
480decd1bdSMatthew Barth * to the group is missing. Once all services are functional and providing
490decd1bdSMatthew Barth * the event data again, active fan speed changes are allowed.
500decd1bdSMatthew Barth *
510decd1bdSMatthew Barth * @param[in] speed - Speed to set the zone to
520decd1bdSMatthew Barth *
530decd1bdSMatthew Barth * @return Action lambda function
540decd1bdSMatthew Barth * An Action function that sets the zone to the given speed if any service
550decd1bdSMatthew Barth * owners are missing.
560decd1bdSMatthew Barth */
570decd1bdSMatthew Barth Action set_speed_on_missing_owner(uint64_t speed);
580decd1bdSMatthew Barth
590decd1bdSMatthew Barth /**
60b280bfa4SMatthew Barth * @brief An action to set the request speed base
61b280bfa4SMatthew Barth * @details A new target speed is determined using a speed delta being added
62b280bfa4SMatthew Barth * or subtracted, for increases or decrease respectively, from a base speed.
63b280bfa4SMatthew Barth * This base speed defaults to be the current target speed or is set to a
64b280bfa4SMatthew Barth * different base speed(i.e. the fans' tach feedback speed) to request a new
65b280bfa4SMatthew Barth * target from.
66b280bfa4SMatthew Barth *
67b280bfa4SMatthew Barth * @param[in] zone - Zone containing fans
68b280bfa4SMatthew Barth * @param[in] group - Group of sensors to determine base from
69b280bfa4SMatthew Barth */
70b280bfa4SMatthew Barth void set_request_speed_base_with_max(Zone& zone, const Group& group);
71b280bfa4SMatthew Barth
72b280bfa4SMatthew Barth /**
7317d1fe23SMatthew Barth * @brief An action to set the speed on a zone
74861d77c3SMatthew Barth * @details The zone is held at the given speed when a defined number of
7517d1fe23SMatthew Barth * properties in the group are set to the given state
7617d1fe23SMatthew Barth *
7717d1fe23SMatthew Barth * @param[in] count - Number of properties
7817d1fe23SMatthew Barth * @param[in] state - Value the property(s) needed to be set at
7917d1fe23SMatthew Barth * @param[in] speed - Speed to set the zone to
8017d1fe23SMatthew Barth *
8117d1fe23SMatthew Barth * @return Lambda function
8217d1fe23SMatthew Barth * A lambda function to set the zone speed when the number of properties
8317d1fe23SMatthew Barth * within the group are at a certain value
8417d1fe23SMatthew Barth */
859e741ed0SMatthew Barth template <typename T>
count_state_before_speed(size_t count,T && state,uint64_t speed)869e741ed0SMatthew Barth auto count_state_before_speed(size_t count, T&& state, uint64_t speed)
8717d1fe23SMatthew Barth {
88dfddd648SPatrick Williams return [count, speed,
89dfddd648SPatrick Williams state = std::forward<T>(state)](auto& zone, auto& group) {
90e0f67c8bSMatthew Barth size_t numAtState = 0;
91e0f67c8bSMatthew Barth for (auto& entry : group)
9217d1fe23SMatthew Barth {
93bc651609SMatthew Barth try
94bc651609SMatthew Barth {
95e0f67c8bSMatthew Barth if (zone.template getPropertyValue<T>(
963e1bb274SMatthew Barth std::get<pathPos>(entry), std::get<intfPos>(entry),
97146b7390SMatthew Barth std::get<propPos>(entry)) == state)
98e0f67c8bSMatthew Barth {
99e0f67c8bSMatthew Barth numAtState++;
100e0f67c8bSMatthew Barth }
101bc651609SMatthew Barth }
102bc651609SMatthew Barth catch (const std::out_of_range& oore)
103bc651609SMatthew Barth {
104bc651609SMatthew Barth // Default to property not equal when not found
105bc651609SMatthew Barth }
10617d1fe23SMatthew Barth if (numAtState >= count)
10717d1fe23SMatthew Barth {
10817d1fe23SMatthew Barth zone.setSpeed(speed);
109e0f67c8bSMatthew Barth break;
110e0f67c8bSMatthew Barth }
11117d1fe23SMatthew Barth }
11260b00766SMatthew Barth // Update group's fan control active allowed based on action results
11360b00766SMatthew Barth zone.setActiveAllow(&group, !(numAtState >= count));
11417d1fe23SMatthew Barth };
11517d1fe23SMatthew Barth }
11617d1fe23SMatthew Barth
1174af419cdSMatthew Barth /**
1184af419cdSMatthew Barth * @brief An action to set the floor speed on a zone
1194af419cdSMatthew Barth * @details Based on the average of the defined sensor group values, the floor
1204af419cdSMatthew Barth * speed is selected from the first map key entry that the average sensor value
1214af419cdSMatthew Barth * is less than.
1224af419cdSMatthew Barth *
1234af419cdSMatthew Barth * @param[in] val_to_speed - Ordered map of sensor value-to-speed
1244af419cdSMatthew Barth *
125b280bfa4SMatthew Barth * @return Action lambda function
126b280bfa4SMatthew Barth * An Action function to set the zone's floor speed when the average of
1274af419cdSMatthew Barth * property values within the group is below the lowest sensor value given
1284af419cdSMatthew Barth */
1299ca6065cSMatthew Barth template <typename T>
set_floor_from_average_sensor_value(std::map<T,uint64_t> && val_to_speed)1303e1bb274SMatthew Barth Action set_floor_from_average_sensor_value(std::map<T, uint64_t>&& val_to_speed)
1319ca6065cSMatthew Barth {
1329ca6065cSMatthew Barth return [val_to_speed = std::move(val_to_speed)](control::Zone& zone,
1333e1bb274SMatthew Barth const Group& group) {
1349ca6065cSMatthew Barth auto speed = zone.getDefFloor();
1359ca6065cSMatthew Barth if (group.size() != 0)
1369ca6065cSMatthew Barth {
1379ca6065cSMatthew Barth auto count = 0;
138dfddd648SPatrick Williams auto sumValue = std::accumulate(
139dfddd648SPatrick Williams group.begin(), group.end(), 0,
140dfddd648SPatrick Williams [&zone, &count](T sum, const auto& entry) {
1419ca6065cSMatthew Barth try
1429ca6065cSMatthew Barth {
1433e1bb274SMatthew Barth return sum + zone.template getPropertyValue<T>(
1449ca6065cSMatthew Barth std::get<pathPos>(entry),
1459ca6065cSMatthew Barth std::get<intfPos>(entry),
1469ca6065cSMatthew Barth std::get<propPos>(entry));
1479ca6065cSMatthew Barth }
1489ca6065cSMatthew Barth catch (const std::out_of_range& oore)
1499ca6065cSMatthew Barth {
1509ca6065cSMatthew Barth count++;
1519ca6065cSMatthew Barth return sum;
1529ca6065cSMatthew Barth }
1539ca6065cSMatthew Barth });
1549ca6065cSMatthew Barth if ((group.size() - count) > 0)
1559ca6065cSMatthew Barth {
1569ca6065cSMatthew Barth auto groupSize = static_cast<int64_t>(group.size());
1579ca6065cSMatthew Barth auto avgValue = sumValue / (groupSize - count);
1583e1bb274SMatthew Barth auto it = std::find_if(val_to_speed.begin(), val_to_speed.end(),
159dfddd648SPatrick Williams [&avgValue](const auto& entry) {
1609ca6065cSMatthew Barth return avgValue < entry.first;
1613e1bb274SMatthew Barth });
1629ca6065cSMatthew Barth if (it != std::end(val_to_speed))
1639ca6065cSMatthew Barth {
1649ca6065cSMatthew Barth speed = (*it).second;
1659ca6065cSMatthew Barth }
1669ca6065cSMatthew Barth }
1679ca6065cSMatthew Barth }
1689ca6065cSMatthew Barth zone.setFloor(speed);
1699ca6065cSMatthew Barth };
1709ca6065cSMatthew Barth }
1714af419cdSMatthew Barth
172e0ca13ebSMatthew Barth /**
173e0ca13ebSMatthew Barth * @brief An action to set the ceiling speed on a zone
174b280bfa4SMatthew Barth * @details Based on the average of the defined sensor group values, the
175b280bfa4SMatthew Barth * ceiling speed is selected from the map key transition point that the average
176b280bfa4SMatthew Barth * sensor value falls within depending on the key values direction from what
177b280bfa4SMatthew Barth * was previously read.
178e0ca13ebSMatthew Barth *
179e0ca13ebSMatthew Barth * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions
180e0ca13ebSMatthew Barth *
181b280bfa4SMatthew Barth * @return Action lambda function
182b280bfa4SMatthew Barth * An Action function to set the zone's ceiling speed when the average of
183e0ca13ebSMatthew Barth * property values within the group is above(increasing) or
184e0ca13ebSMatthew Barth * below(decreasing) the key transition point
185e0ca13ebSMatthew Barth */
1869ca6065cSMatthew Barth template <typename T>
set_ceiling_from_average_sensor_value(std::map<T,uint64_t> && val_to_speed)187*4fa67aa1SPatrick Williams Action set_ceiling_from_average_sensor_value(
188*4fa67aa1SPatrick Williams std::map<T, uint64_t>&& val_to_speed)
1899ca6065cSMatthew Barth {
190dfddd648SPatrick Williams return [val_to_speed =
191dfddd648SPatrick Williams std::move(val_to_speed)](Zone& zone, const Group& group) {
1929ca6065cSMatthew Barth auto speed = zone.getCeiling();
1939ca6065cSMatthew Barth if (group.size() != 0)
1949ca6065cSMatthew Barth {
1959ca6065cSMatthew Barth auto count = 0;
196dfddd648SPatrick Williams auto sumValue = std::accumulate(
197dfddd648SPatrick Williams group.begin(), group.end(), 0,
198dfddd648SPatrick Williams [&zone, &count](T sum, const auto& entry) {
1999ca6065cSMatthew Barth try
2009ca6065cSMatthew Barth {
2013e1bb274SMatthew Barth return sum + zone.template getPropertyValue<T>(
2029ca6065cSMatthew Barth std::get<pathPos>(entry),
2039ca6065cSMatthew Barth std::get<intfPos>(entry),
2049ca6065cSMatthew Barth std::get<propPos>(entry));
2059ca6065cSMatthew Barth }
2069ca6065cSMatthew Barth catch (const std::out_of_range& oore)
2079ca6065cSMatthew Barth {
2089ca6065cSMatthew Barth count++;
2099ca6065cSMatthew Barth return sum;
2109ca6065cSMatthew Barth }
2119ca6065cSMatthew Barth });
2129ca6065cSMatthew Barth if ((group.size() - count) > 0)
2139ca6065cSMatthew Barth {
2149ca6065cSMatthew Barth auto groupSize = static_cast<int64_t>(group.size());
2159ca6065cSMatthew Barth auto avgValue = sumValue / (groupSize - count);
2169ca6065cSMatthew Barth auto prevValue = zone.swapCeilingKeyValue(avgValue);
2179ca6065cSMatthew Barth if (avgValue != prevValue)
2189ca6065cSMatthew Barth { // Only check if previous and new values differ
2199ca6065cSMatthew Barth if (avgValue < prevValue)
2209ca6065cSMatthew Barth { // Value is decreasing from previous
2219ca6065cSMatthew Barth for (auto it = val_to_speed.rbegin();
2223e1bb274SMatthew Barth it != val_to_speed.rend(); ++it)
2239ca6065cSMatthew Barth {
2249ca6065cSMatthew Barth if (it == val_to_speed.rbegin() &&
2259ca6065cSMatthew Barth avgValue >= it->first)
2269ca6065cSMatthew Barth {
2279ca6065cSMatthew Barth // Value is at/above last map key, set
2289ca6065cSMatthew Barth // ceiling speed to the last map key's value
2299ca6065cSMatthew Barth speed = it->second;
2309ca6065cSMatthew Barth break;
2319ca6065cSMatthew Barth }
2329ca6065cSMatthew Barth else if (std::next(it, 1) == val_to_speed.rend() &&
2339ca6065cSMatthew Barth avgValue <= it->first)
2349ca6065cSMatthew Barth {
2359ca6065cSMatthew Barth // Value is at/below first map key, set
2369ca6065cSMatthew Barth // ceiling speed to the first map key's value
2379ca6065cSMatthew Barth speed = it->second;
2389ca6065cSMatthew Barth break;
2399ca6065cSMatthew Barth }
2403e1bb274SMatthew Barth if (avgValue < it->first && it->first <= prevValue)
2419ca6065cSMatthew Barth {
2429ca6065cSMatthew Barth // Value decreased & transitioned across
2439ca6065cSMatthew Barth // a map key, update ceiling speed to this
2449ca6065cSMatthew Barth // map key's value when new value is below
2459ca6065cSMatthew Barth // map's key and the key is at/below the
2469ca6065cSMatthew Barth // previous value
2479ca6065cSMatthew Barth speed = it->second;
2489ca6065cSMatthew Barth }
2499ca6065cSMatthew Barth }
2509ca6065cSMatthew Barth }
2519ca6065cSMatthew Barth else
2529ca6065cSMatthew Barth { // Value is increasing from previous
2539ca6065cSMatthew Barth for (auto it = val_to_speed.begin();
2543e1bb274SMatthew Barth it != val_to_speed.end(); ++it)
2559ca6065cSMatthew Barth {
2569ca6065cSMatthew Barth if (it == val_to_speed.begin() &&
2579ca6065cSMatthew Barth avgValue <= it->first)
2589ca6065cSMatthew Barth {
2599ca6065cSMatthew Barth // Value is at/below first map key, set
2609ca6065cSMatthew Barth // ceiling speed to the first map key's value
2619ca6065cSMatthew Barth speed = it->second;
2629ca6065cSMatthew Barth break;
2639ca6065cSMatthew Barth }
2649ca6065cSMatthew Barth else if (std::next(it, 1) == val_to_speed.end() &&
2659ca6065cSMatthew Barth avgValue >= it->first)
2669ca6065cSMatthew Barth {
2679ca6065cSMatthew Barth // Value is at/above last map key, set
2689ca6065cSMatthew Barth // ceiling speed to the last map key's value
2699ca6065cSMatthew Barth speed = it->second;
2709ca6065cSMatthew Barth break;
2719ca6065cSMatthew Barth }
2723e1bb274SMatthew Barth if (avgValue > it->first && it->first >= prevValue)
2739ca6065cSMatthew Barth {
2749ca6065cSMatthew Barth // Value increased & transitioned across
2759ca6065cSMatthew Barth // a map key, update ceiling speed to this
2769ca6065cSMatthew Barth // map key's value when new value is above
2779ca6065cSMatthew Barth // map's key and the key is at/above the
2789ca6065cSMatthew Barth // previous value
2799ca6065cSMatthew Barth speed = it->second;
2809ca6065cSMatthew Barth }
2819ca6065cSMatthew Barth }
2829ca6065cSMatthew Barth }
2839ca6065cSMatthew Barth }
2849ca6065cSMatthew Barth }
2859ca6065cSMatthew Barth }
2869ca6065cSMatthew Barth zone.setCeiling(speed);
2879ca6065cSMatthew Barth };
2889ca6065cSMatthew Barth }
289e0ca13ebSMatthew Barth
29024623523SMatthew Barth /**
29124623523SMatthew Barth * @brief An action to set the speed increase delta and request speed change
29224623523SMatthew Barth * @details Provides the ability to determine what the net increase delta the
29324623523SMatthew Barth * zone's fan speeds should be updated by from their current target speed and
29424623523SMatthew Barth * request that new target speed.
29524623523SMatthew Barth *
29624623523SMatthew Barth * @param[in] state - State to compare the group's property value to
297172f3936SMatthew Barth * @param[in] factor - Factor to apply to the calculated net delta
29824623523SMatthew Barth * @param[in] speedDelta - Speed delta of the group
29924623523SMatthew Barth *
30024623523SMatthew Barth * @return Lambda function
30124623523SMatthew Barth * A lambda function that determines the net increase delta and requests
30224623523SMatthew Barth * a new target speed with that increase for the zone.
30324623523SMatthew Barth */
30424623523SMatthew Barth template <typename T>
set_net_increase_speed(T && state,T && factor,uint64_t speedDelta)305172f3936SMatthew Barth auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta)
30624623523SMatthew Barth {
3073e1bb274SMatthew Barth return [speedDelta, factor = std::forward<T>(factor),
3083e1bb274SMatthew Barth state = std::forward<T>(state)](auto& zone, auto& group) {
30924623523SMatthew Barth auto netDelta = zone.getIncSpeedDelta();
310dfddd648SPatrick Williams std::for_each(
311dfddd648SPatrick Williams group.begin(), group.end(),
3123e1bb274SMatthew Barth [&zone, &state, &factor, &speedDelta,
313dfddd648SPatrick Williams &netDelta](const auto& entry) {
314bc651609SMatthew Barth try
31524623523SMatthew Barth {
31624623523SMatthew Barth T value = zone.template getPropertyValue<T>(
3173e1bb274SMatthew Barth std::get<pathPos>(entry), std::get<intfPos>(entry),
318146b7390SMatthew Barth std::get<propPos>(entry));
31924623523SMatthew Barth // TODO openbmc/phosphor-fan-presence#7 - Support possible
32024623523SMatthew Barth // state types for comparison
32124623523SMatthew Barth if (value >= state)
32224623523SMatthew Barth {
323172f3936SMatthew Barth // Increase by at least a single delta(factor)
32424623523SMatthew Barth // to attempt bringing under 'state'
3253e1bb274SMatthew Barth auto delta = std::max((value - state), factor);
326172f3936SMatthew Barth // Increase is the factor applied to the
327172f3936SMatthew Barth // difference times the given speed delta
328dfddd648SPatrick Williams netDelta = std::max(netDelta,
329dfddd648SPatrick Williams static_cast<uint64_t>(
330dfddd648SPatrick Williams (delta / factor) * speedDelta));
33124623523SMatthew Barth }
33224623523SMatthew Barth }
333bc651609SMatthew Barth catch (const std::out_of_range& oore)
334bc651609SMatthew Barth {
335bc651609SMatthew Barth // Property value not found, netDelta unchanged
336bc651609SMatthew Barth }
3373e1bb274SMatthew Barth });
338240397b9SMatthew Barth // Request speed change for target speed update
339240397b9SMatthew Barth zone.requestSpeedIncrease(netDelta);
34024623523SMatthew Barth };
34124623523SMatthew Barth }
34224623523SMatthew Barth
3430ce99d8bSMatthew Barth /**
3440ce99d8bSMatthew Barth * @brief An action to set the speed decrease delta and request speed change
3450ce99d8bSMatthew Barth * @details Provides the ability to determine what the net decrease delta each
3460ce99d8bSMatthew Barth * zone's fan speeds should be updated by from their current target speed, and
3470ce99d8bSMatthew Barth * request that speed change occur on the next decrease interval.
3480ce99d8bSMatthew Barth *
3490ce99d8bSMatthew Barth * @param[in] state - State to compare the group's property value to
350172f3936SMatthew Barth * @param[in] factor - Factor to apply to the calculated net delta
3510ce99d8bSMatthew Barth * @param[in] speedDelta - Speed delta of the group
3520ce99d8bSMatthew Barth *
3530ce99d8bSMatthew Barth * @return Lambda function
3540ce99d8bSMatthew Barth * A lambda function that determines the net decrease delta and requests
3550ce99d8bSMatthew Barth * a new target speed with that decrease for the zone.
3560ce99d8bSMatthew Barth */
3570ce99d8bSMatthew Barth template <typename T>
set_net_decrease_speed(T && state,T && factor,uint64_t speedDelta)358172f3936SMatthew Barth auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta)
3590ce99d8bSMatthew Barth {
3603e1bb274SMatthew Barth return [speedDelta, factor = std::forward<T>(factor),
3613e1bb274SMatthew Barth state = std::forward<T>(state)](auto& zone, auto& group) {
3620ce99d8bSMatthew Barth auto netDelta = zone.getDecSpeedDelta();
363e4338cdbSMatthew Barth for (auto& entry : group)
3640ce99d8bSMatthew Barth {
365bc651609SMatthew Barth try
366bc651609SMatthew Barth {
3670ce99d8bSMatthew Barth T value = zone.template getPropertyValue<T>(
3683e1bb274SMatthew Barth std::get<pathPos>(entry), std::get<intfPos>(entry),
369146b7390SMatthew Barth std::get<propPos>(entry));
3700ce99d8bSMatthew Barth // TODO openbmc/phosphor-fan-presence#7 - Support possible
3710ce99d8bSMatthew Barth // state types for comparison
3720ce99d8bSMatthew Barth if (value < state)
3730ce99d8bSMatthew Barth {
3740ce99d8bSMatthew Barth if (netDelta == 0)
3750ce99d8bSMatthew Barth {
376172f3936SMatthew Barth netDelta = ((state - value) / factor) * speedDelta;
3770ce99d8bSMatthew Barth }
3780ce99d8bSMatthew Barth else
3790ce99d8bSMatthew Barth {
380172f3936SMatthew Barth // Decrease is the factor applied to the
381172f3936SMatthew Barth // difference times the given speed delta
382172f3936SMatthew Barth netDelta = std::min(
383172f3936SMatthew Barth netDelta,
384dfddd648SPatrick Williams static_cast<uint64_t>(
385dfddd648SPatrick Williams ((state - value) / factor) * speedDelta));
3860ce99d8bSMatthew Barth }
3870ce99d8bSMatthew Barth }
388e4338cdbSMatthew Barth else
389e4338cdbSMatthew Barth {
390e4338cdbSMatthew Barth // No decrease allowed for this group
391e4338cdbSMatthew Barth netDelta = 0;
392e4338cdbSMatthew Barth break;
393e4338cdbSMatthew Barth }
3940ce99d8bSMatthew Barth }
395bc651609SMatthew Barth catch (const std::out_of_range& oore)
396bc651609SMatthew Barth {
397bc651609SMatthew Barth // Property value not found, netDelta unchanged
398bc651609SMatthew Barth }
399bc651609SMatthew Barth }
400e4338cdbSMatthew Barth // Update group's decrease allowed state
401e4338cdbSMatthew Barth zone.setDecreaseAllow(&group, !(netDelta == 0));
4020ce99d8bSMatthew Barth // Request speed decrease to occur on decrease interval
4030ce99d8bSMatthew Barth zone.requestSpeedDecrease(netDelta);
4040ce99d8bSMatthew Barth };
4050ce99d8bSMatthew Barth }
4060ce99d8bSMatthew Barth
407c410ddabSMatthew Barth /**
408c410ddabSMatthew Barth * @brief An action to use an alternate set of events
409c410ddabSMatthew Barth * @details Provides the ability to replace a default set of events with an
410c410ddabSMatthew Barth * alternate set of events based on all members of a group being at a specified
411c410ddabSMatthew Barth * state. When any member of the group no longer matches the provided state,
412c410ddabSMatthew Barth * the alternate set of events are replaced with the defaults.
413c410ddabSMatthew Barth *
414c410ddabSMatthew Barth * @param[in] state - State to compare the group's property value to
415c410ddabSMatthew Barth * @param[in] defEvents - The default set of events
416c410ddabSMatthew Barth * @param[in] altEvents - The alternate set of events
417c410ddabSMatthew Barth *
418c410ddabSMatthew Barth * @return Lambda function
419c410ddabSMatthew Barth * A lambda function that checks all group members are at a specified state
420c410ddabSMatthew Barth * and replacing the default set of events with an alternate set of events.
421c410ddabSMatthew Barth */
422c410ddabSMatthew Barth template <typename T>
use_alternate_events_on_state(T && state,std::vector<SetSpeedEvent> && defEvents,std::vector<SetSpeedEvent> && altEvents)423c410ddabSMatthew Barth auto use_alternate_events_on_state(T&& state,
424c410ddabSMatthew Barth std::vector<SetSpeedEvent>&& defEvents,
425c410ddabSMatthew Barth std::vector<SetSpeedEvent>&& altEvents)
426c410ddabSMatthew Barth {
4273e1bb274SMatthew Barth return [state = std::forward<T>(state), defEvents = std::move(defEvents),
4283e1bb274SMatthew Barth altEvents = std::move(altEvents)](auto& zone, auto& group) {
429c410ddabSMatthew Barth // Compare all group entries to the state
430dfddd648SPatrick Williams auto useAlt = std::all_of(
431dfddd648SPatrick Williams group.begin(), group.end(), [&zone, &state](const auto& entry) {
432c410ddabSMatthew Barth try
433c410ddabSMatthew Barth {
434c410ddabSMatthew Barth return zone.template getPropertyValue<T>(
435dfddd648SPatrick Williams std::get<pathPos>(entry),
436dfddd648SPatrick Williams std::get<intfPos>(entry),
437146b7390SMatthew Barth std::get<propPos>(entry)) == state;
438c410ddabSMatthew Barth }
439c410ddabSMatthew Barth catch (const std::out_of_range& oore)
440c410ddabSMatthew Barth {
441c410ddabSMatthew Barth // Default to property not equal when not found
442c410ddabSMatthew Barth return false;
443c410ddabSMatthew Barth }
444c410ddabSMatthew Barth });
445c410ddabSMatthew Barth
446c410ddabSMatthew Barth const std::vector<SetSpeedEvent>* rmEvents = &altEvents;
447c410ddabSMatthew Barth const std::vector<SetSpeedEvent>* initEvents = &defEvents;
448c410ddabSMatthew Barth
449c410ddabSMatthew Barth if (useAlt)
450c410ddabSMatthew Barth {
451c410ddabSMatthew Barth rmEvents = &defEvents;
452c410ddabSMatthew Barth initEvents = &altEvents;
453c410ddabSMatthew Barth }
454c410ddabSMatthew Barth
455c410ddabSMatthew Barth // Remove events
4563e1bb274SMatthew Barth std::for_each(rmEvents->begin(), rmEvents->end(),
457dfddd648SPatrick Williams [&zone](const auto& entry) { zone.removeEvent(entry); });
458c410ddabSMatthew Barth // Init events
4593e1bb274SMatthew Barth std::for_each(initEvents->begin(), initEvents->end(),
460dfddd648SPatrick Williams [&zone](const auto& entry) { zone.initEvent(entry); });
461c410ddabSMatthew Barth };
462c410ddabSMatthew Barth }
463c410ddabSMatthew Barth
464014f07c7SMatthew Barth /**
465014f07c7SMatthew Barth * @brief An action to set the floor speed on a zone
466014f07c7SMatthew Barth * @details Using sensor group values that are within a defined range, the
467014f07c7SMatthew Barth * floor speed is selected from the first map key entry that the median
468014f07c7SMatthew Barth * sensor value is less than where 3 or more sensor group values are valid.
469014f07c7SMatthew Barth * In the case where less than 3 sensor values are valid, use the highest
470014f07c7SMatthew Barth * sensor group value and default the floor speed when 0 sensor group values
471014f07c7SMatthew Barth * are valid.
472014f07c7SMatthew Barth *
473014f07c7SMatthew Barth * @param[in] lowerBound - Lowest allowed sensor value to be valid
474014f07c7SMatthew Barth * @param[in] upperBound - Highest allowed sensor value to be valid
475014f07c7SMatthew Barth * @param[in] valueToSpeed - Ordered map of sensor value-to-speed
476014f07c7SMatthew Barth *
477014f07c7SMatthew Barth * @return Action lambda function
478014f07c7SMatthew Barth * An Action function to set the zone's floor speed from a resulting group
479014f07c7SMatthew Barth * of valid sensor values based on their highest value or median.
480014f07c7SMatthew Barth */
4819ca6065cSMatthew Barth template <typename T>
set_floor_from_median_sensor_value(T && lowerBound,T && upperBound,std::map<T,uint64_t> && valueToSpeed)4823e1bb274SMatthew Barth Action set_floor_from_median_sensor_value(T&& lowerBound, T&& upperBound,
4839ca6065cSMatthew Barth std::map<T, uint64_t>&& valueToSpeed)
4849ca6065cSMatthew Barth {
4859ca6065cSMatthew Barth return [lowerBound = std::forward<T>(lowerBound),
4869ca6065cSMatthew Barth upperBound = std::forward<T>(upperBound),
4879ca6065cSMatthew Barth valueToSpeed = std::move(valueToSpeed)](control::Zone& zone,
4883e1bb274SMatthew Barth const Group& group) {
4899ca6065cSMatthew Barth auto speed = zone.getDefFloor();
4909ca6065cSMatthew Barth if (group.size() != 0)
4919ca6065cSMatthew Barth {
4929ca6065cSMatthew Barth std::vector<T> validValues;
493dfddd648SPatrick Williams for (const auto& member : group)
4949ca6065cSMatthew Barth {
4959ca6065cSMatthew Barth try
4969ca6065cSMatthew Barth {
4979ca6065cSMatthew Barth auto value = zone.template getPropertyValue<T>(
4983e1bb274SMatthew Barth std::get<pathPos>(member), std::get<intfPos>(member),
4999ca6065cSMatthew Barth std::get<propPos>(member));
5009ca6065cSMatthew Barth if (value == std::clamp(value, lowerBound, upperBound))
5019ca6065cSMatthew Barth {
5029ca6065cSMatthew Barth // Sensor value is valid
5039ca6065cSMatthew Barth validValues.emplace_back(value);
5049ca6065cSMatthew Barth }
5059ca6065cSMatthew Barth }
5069ca6065cSMatthew Barth catch (const std::out_of_range& oore)
5079ca6065cSMatthew Barth {
5089ca6065cSMatthew Barth continue;
5099ca6065cSMatthew Barth }
5109ca6065cSMatthew Barth }
5119ca6065cSMatthew Barth
5129ca6065cSMatthew Barth if (!validValues.empty())
5139ca6065cSMatthew Barth {
5149ca6065cSMatthew Barth auto median = validValues.front();
5159ca6065cSMatthew Barth // Get the determined median value
5169ca6065cSMatthew Barth if (validValues.size() == 2)
5179ca6065cSMatthew Barth {
5189ca6065cSMatthew Barth // For 2 values, use the highest instead of the average
5199ca6065cSMatthew Barth // for a thermally safe floor
5209ca6065cSMatthew Barth median = *std::max_element(validValues.begin(),
5219ca6065cSMatthew Barth validValues.end());
5229ca6065cSMatthew Barth }
5239ca6065cSMatthew Barth else if (validValues.size() > 2)
5249ca6065cSMatthew Barth {
5259ca6065cSMatthew Barth median = utility::getMedian(validValues);
5269ca6065cSMatthew Barth }
5279ca6065cSMatthew Barth
5289ca6065cSMatthew Barth // Use determined median sensor value to find floor speed
5293e1bb274SMatthew Barth auto it = std::find_if(valueToSpeed.begin(), valueToSpeed.end(),
530dfddd648SPatrick Williams [&median](const auto& entry) {
5319ca6065cSMatthew Barth return median < entry.first;
5323e1bb274SMatthew Barth });
5339ca6065cSMatthew Barth if (it != std::end(valueToSpeed))
5349ca6065cSMatthew Barth {
5359ca6065cSMatthew Barth speed = (*it).second;
5369ca6065cSMatthew Barth }
5379ca6065cSMatthew Barth }
5389ca6065cSMatthew Barth }
5399ca6065cSMatthew Barth zone.setFloor(speed);
5409ca6065cSMatthew Barth };
5419ca6065cSMatthew Barth }
542014f07c7SMatthew Barth
5438d06a838SMatthew Barth /**
5448d06a838SMatthew Barth * @brief An action to update the default floor speed
5458d06a838SMatthew Barth * @details Provides the ability to update the default fan floor speed when
5468d06a838SMatthew Barth * all of the group members property values match the value given
5478d06a838SMatthew Barth *
5488d06a838SMatthew Barth * @param[in] state - State to compare the group's property value to
5498d06a838SMatthew Barth * @param[in] speed - Speed to set the default fan floor to
5508d06a838SMatthew Barth *
5518d06a838SMatthew Barth * @return Lambda function
5528d06a838SMatthew Barth * A lambda function that checks all group members are at a specified state
5538d06a838SMatthew Barth * and updates the default fan floor speed.
5548d06a838SMatthew Barth */
5558d06a838SMatthew Barth template <typename T>
update_default_floor(T && state,uint64_t speed)5568d06a838SMatthew Barth auto update_default_floor(T&& state, uint64_t speed)
5578d06a838SMatthew Barth {
5583e1bb274SMatthew Barth return [speed, state = std::forward<T>(state)](auto& zone, auto& group) {
559dfddd648SPatrick Williams auto updateDefFloor = std::all_of(
560dfddd648SPatrick Williams group.begin(), group.end(), [&zone, &state](const auto& entry) {
5618d06a838SMatthew Barth try
5628d06a838SMatthew Barth {
5638d06a838SMatthew Barth return zone.template getPropertyValue<T>(
564dfddd648SPatrick Williams std::get<pathPos>(entry),
565dfddd648SPatrick Williams std::get<intfPos>(entry),
5668d06a838SMatthew Barth std::get<propPos>(entry)) == state;
5678d06a838SMatthew Barth }
5688d06a838SMatthew Barth catch (const std::out_of_range& oore)
5698d06a838SMatthew Barth {
5708d06a838SMatthew Barth // Default to property not equal when not found
5718d06a838SMatthew Barth return false;
5728d06a838SMatthew Barth }
5738d06a838SMatthew Barth });
5748d06a838SMatthew Barth
5758d06a838SMatthew Barth if (!updateDefFloor)
5768d06a838SMatthew Barth {
5778d06a838SMatthew Barth // Do not update the default floor
5788d06a838SMatthew Barth return;
5798d06a838SMatthew Barth }
5808d06a838SMatthew Barth
5818d06a838SMatthew Barth // Set/update the default floor of the zone
5828d06a838SMatthew Barth zone.setDefFloor(speed);
5838d06a838SMatthew Barth };
5848d06a838SMatthew Barth }
5858d06a838SMatthew Barth
586799cdf74SMatthew Barth /**
587799cdf74SMatthew Barth * @brief An action to use a set of events
588799cdf74SMatthew Barth * @details Provides the ability to use a set of events when all members of
589799cdf74SMatthew Barth * a group are at a specified state. When any member of the group no longer
590799cdf74SMatthew Barth * matches the provided state the set of events are removed.
591799cdf74SMatthew Barth *
592799cdf74SMatthew Barth * @param[in] state - State to compare the group's property value to
593799cdf74SMatthew Barth * @param[in] events - The set of events
594799cdf74SMatthew Barth *
595799cdf74SMatthew Barth * @return Lambda function
596799cdf74SMatthew Barth * A lambda function that checks all group members are at a specified state
597799cdf74SMatthew Barth * and initializes the set of events, otherwise removes them.
598799cdf74SMatthew Barth */
599799cdf74SMatthew Barth template <typename T>
use_events_on_state(T && state,std::vector<SetSpeedEvent> && events)6003e1bb274SMatthew Barth auto use_events_on_state(T&& state, std::vector<SetSpeedEvent>&& events)
601799cdf74SMatthew Barth {
602799cdf74SMatthew Barth return [state = std::forward<T>(state),
6033e1bb274SMatthew Barth events = std::move(events)](auto& zone, auto& group) {
604799cdf74SMatthew Barth // Compare all group entries to the state
605dfddd648SPatrick Williams auto useEvents = std::all_of(
606dfddd648SPatrick Williams group.begin(), group.end(), [&zone, &state](const auto& entry) {
607799cdf74SMatthew Barth try
608799cdf74SMatthew Barth {
609799cdf74SMatthew Barth return zone.template getPropertyValue<T>(
610dfddd648SPatrick Williams std::get<pathPos>(entry),
611dfddd648SPatrick Williams std::get<intfPos>(entry),
612799cdf74SMatthew Barth std::get<propPos>(entry)) == state;
613799cdf74SMatthew Barth }
614799cdf74SMatthew Barth catch (const std::out_of_range& oore)
615799cdf74SMatthew Barth {
616799cdf74SMatthew Barth // Default to property not equal when not found
617799cdf74SMatthew Barth return false;
618799cdf74SMatthew Barth }
619799cdf74SMatthew Barth });
620799cdf74SMatthew Barth
621799cdf74SMatthew Barth if (useEvents)
622799cdf74SMatthew Barth {
623799cdf74SMatthew Barth // Init events
624dfddd648SPatrick Williams std::for_each(events.begin(), events.end(),
625dfddd648SPatrick Williams [&zone](const auto& entry) {
626dfddd648SPatrick Williams zone.initEvent(entry);
627dfddd648SPatrick Williams });
628799cdf74SMatthew Barth }
629799cdf74SMatthew Barth else
630799cdf74SMatthew Barth {
631799cdf74SMatthew Barth // Remove events
632dfddd648SPatrick Williams std::for_each(events.begin(), events.end(),
633dfddd648SPatrick Williams [&zone](const auto& entry) {
634dfddd648SPatrick Williams zone.removeEvent(entry);
635dfddd648SPatrick Williams });
636799cdf74SMatthew Barth }
637799cdf74SMatthew Barth };
638799cdf74SMatthew Barth }
639799cdf74SMatthew Barth
64017d1fe23SMatthew Barth } // namespace action
64117d1fe23SMatthew Barth } // namespace control
64217d1fe23SMatthew Barth } // namespace fan
64317d1fe23SMatthew Barth } // namespace phosphor
644