blob: fff825074394466e6f88c7f694e5b820c2e9c41c [file] [log] [blame]
Matthew Barth17d1fe22017-05-11 15:00:36 -05001#pragma once
2
3#include <algorithm>
Matthew Barth4af419c2017-06-12 13:39:31 -05004#include <numeric>
Matthew Barthb280bfa2017-09-15 09:56:50 -05005#include "types.hpp"
6#include "zone.hpp"
Matthew Barth17d1fe22017-05-11 15:00:36 -05007
8namespace phosphor
9{
10namespace fan
11{
12namespace control
13{
14namespace action
15{
16
17/**
Matthew Barth2a646c52017-10-05 17:04:11 -050018 * @brief An action that wraps a list of actions with a timer
19 * @details Sets up a list of actions to be invoked when the defined timer
20 * expires (or for each expiration of a repeating timer).
21 *
22 * @param[in] tConf - Timer configuration parameters
23 * @param[in] action - List of actions to be called when the timer expires
24 *
25 * @return Action lambda function
26 * An Action function that creates a timer
27 */
28Action call_actions_based_on_timer(
29 Timer&& tConf,
30 std::vector<Action>&& actions);
31
32/**
Matthew Barthb280bfa2017-09-15 09:56:50 -050033 * @brief An action to set the request speed base
34 * @details A new target speed is determined using a speed delta being added
35 * or subtracted, for increases or decrease respectively, from a base speed.
36 * This base speed defaults to be the current target speed or is set to a
37 * different base speed(i.e. the fans' tach feedback speed) to request a new
38 * target from.
39 *
40 * @param[in] zone - Zone containing fans
41 * @param[in] group - Group of sensors to determine base from
42 */
43void set_request_speed_base_with_max(Zone& zone, const Group& group);
44
45/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050046 * @brief An action to set the speed on a zone
Matthew Barth861d77c2017-05-22 14:18:25 -050047 * @details The zone is held at the given speed when a defined number of
Matthew Barth17d1fe22017-05-11 15:00:36 -050048 * properties in the group are set to the given state
49 *
50 * @param[in] count - Number of properties
51 * @param[in] state - Value the property(s) needed to be set at
52 * @param[in] speed - Speed to set the zone to
53 *
54 * @return Lambda function
55 * A lambda function to set the zone speed when the number of properties
56 * within the group are at a certain value
57 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050058template <typename T>
59auto count_state_before_speed(size_t count, T&& state, uint64_t speed)
Matthew Barth17d1fe22017-05-11 15:00:36 -050060{
Matthew Barth9e741ed2017-06-02 16:29:09 -050061 return [count,
62 speed,
63 state = std::forward<T>(state)](auto& zone, auto& group)
Matthew Barth17d1fe22017-05-11 15:00:36 -050064 {
65 size_t numAtState = std::count_if(
66 group.begin(),
67 group.end(),
68 [&zone, &state](auto const& entry)
69 {
Matthew Barthbc651602017-08-10 16:59:43 -050070 try
71 {
72 return zone.template getPropertyValue<T>(
73 entry.first,
74 std::get<intfPos>(entry.second),
75 std::get<propPos>(entry.second)) == state;
76 }
77 catch (const std::out_of_range& oore)
78 {
79 // Default to property not equal when not found
80 return false;
81 }
Matthew Barth17d1fe22017-05-11 15:00:36 -050082 });
Matthew Barth17d1fe22017-05-11 15:00:36 -050083 if (numAtState >= count)
84 {
85 zone.setSpeed(speed);
86 }
Matthew Barth60b00762017-08-15 13:39:06 -050087 // Update group's fan control active allowed based on action results
88 zone.setActiveAllow(&group, !(numAtState >= count));
Matthew Barth17d1fe22017-05-11 15:00:36 -050089 };
90}
91
Matthew Barth4af419c2017-06-12 13:39:31 -050092/**
93 * @brief An action to set the floor speed on a zone
94 * @details Based on the average of the defined sensor group values, the floor
95 * speed is selected from the first map key entry that the average sensor value
96 * is less than.
97 *
98 * @param[in] val_to_speed - Ordered map of sensor value-to-speed
99 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500100 * @return Action lambda function
101 * An Action function to set the zone's floor speed when the average of
Matthew Barth4af419c2017-06-12 13:39:31 -0500102 * property values within the group is below the lowest sensor value given
103 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500104Action set_floor_from_average_sensor_value(
105 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barth4af419c2017-06-12 13:39:31 -0500106
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500107/**
108 * @brief An action to set the ceiling speed on a zone
Matthew Barthb280bfa2017-09-15 09:56:50 -0500109 * @details Based on the average of the defined sensor group values, the
110 * ceiling speed is selected from the map key transition point that the average
111 * sensor value falls within depending on the key values direction from what
112 * was previously read.
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500113 *
114 * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions
115 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500116 * @return Action lambda function
117 * An Action function to set the zone's ceiling speed when the average of
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500118 * property values within the group is above(increasing) or
119 * below(decreasing) the key transition point
120 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500121Action set_ceiling_from_average_sensor_value(
122 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500123
Matthew Barth24623522017-06-21 14:09:57 -0500124/**
125 * @brief An action to set the speed increase delta and request speed change
126 * @details Provides the ability to determine what the net increase delta the
127 * zone's fan speeds should be updated by from their current target speed and
128 * request that new target speed.
129 *
130 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500131 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth24623522017-06-21 14:09:57 -0500132 * @param[in] speedDelta - Speed delta of the group
133 *
134 * @return Lambda function
135 * A lambda function that determines the net increase delta and requests
136 * a new target speed with that increase for the zone.
137 */
138template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500139auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth24623522017-06-21 14:09:57 -0500140{
141 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500142 factor = std::forward<T>(factor),
Matthew Barth24623522017-06-21 14:09:57 -0500143 state = std::forward<T>(state)](auto& zone, auto& group)
144 {
145 auto netDelta = zone.getIncSpeedDelta();
146 std::for_each(
147 group.begin(),
148 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500149 [&zone, &state, &factor, &speedDelta, &netDelta](
Matthew Barthbc651602017-08-10 16:59:43 -0500150 auto const& entry)
Matthew Barth24623522017-06-21 14:09:57 -0500151 {
Matthew Barthbc651602017-08-10 16:59:43 -0500152 try
Matthew Barth24623522017-06-21 14:09:57 -0500153 {
Matthew Barthbc651602017-08-10 16:59:43 -0500154 T value = zone.template getPropertyValue<T>(
155 entry.first,
156 std::get<intfPos>(entry.second),
157 std::get<propPos>(entry.second));
158 // TODO openbmc/phosphor-fan-presence#7 - Support possible
159 // state types for comparison
160 if (value >= state)
161 {
Matthew Barth172f3932017-08-14 11:07:46 -0500162 // Increase by at least a single delta(factor)
Matthew Barthbc651602017-08-10 16:59:43 -0500163 // to attempt bringing under 'state'
Matthew Barth172f3932017-08-14 11:07:46 -0500164 auto delta = std::max(
165 (value - state),
166 factor);
167 // Increase is the factor applied to the
168 // difference times the given speed delta
169 netDelta = std::max(
170 netDelta,
171 (delta/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500172 }
173 }
174 catch (const std::out_of_range& oore)
175 {
176 // Property value not found, netDelta unchanged
Matthew Barth24623522017-06-21 14:09:57 -0500177 }
178 }
179 );
Matthew Barth240397b2017-06-22 11:23:30 -0500180 // Request speed change for target speed update
181 zone.requestSpeedIncrease(netDelta);
Matthew Barth24623522017-06-21 14:09:57 -0500182 };
183}
184
Matthew Barth0ce99d82017-06-22 15:07:29 -0500185/**
186 * @brief An action to set the speed decrease delta and request speed change
187 * @details Provides the ability to determine what the net decrease delta each
188 * zone's fan speeds should be updated by from their current target speed, and
189 * request that speed change occur on the next decrease interval.
190 *
191 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500192 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth0ce99d82017-06-22 15:07:29 -0500193 * @param[in] speedDelta - Speed delta of the group
194 *
195 * @return Lambda function
196 * A lambda function that determines the net decrease delta and requests
197 * a new target speed with that decrease for the zone.
198 */
199template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500200auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500201{
202 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500203 factor = std::forward<T>(factor),
Matthew Barth0ce99d82017-06-22 15:07:29 -0500204 state = std::forward<T>(state)](auto& zone, auto& group)
205 {
206 auto netDelta = zone.getDecSpeedDelta();
207 std::for_each(
208 group.begin(),
209 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500210 [&zone, &state, &factor, &speedDelta, &netDelta](auto const& entry)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500211 {
Matthew Barthbc651602017-08-10 16:59:43 -0500212 try
Matthew Barth0ce99d82017-06-22 15:07:29 -0500213 {
Matthew Barthbc651602017-08-10 16:59:43 -0500214 T value = zone.template getPropertyValue<T>(
215 entry.first,
216 std::get<intfPos>(entry.second),
217 std::get<propPos>(entry.second));
218 // TODO openbmc/phosphor-fan-presence#7 - Support possible
219 // state types for comparison
220 if (value < state)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500221 {
Matthew Barthbc651602017-08-10 16:59:43 -0500222 if (netDelta == 0)
223 {
Matthew Barth172f3932017-08-14 11:07:46 -0500224 netDelta = ((state - value)/factor) * speedDelta;
Matthew Barthbc651602017-08-10 16:59:43 -0500225 }
226 else
227 {
Matthew Barth172f3932017-08-14 11:07:46 -0500228 // Decrease is the factor applied to the
229 // difference times the given speed delta
230 netDelta = std::min(
231 netDelta,
232 ((state - value)/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500233 }
Matthew Barth0ce99d82017-06-22 15:07:29 -0500234 }
Matthew Barthbc651602017-08-10 16:59:43 -0500235 }
236 catch (const std::out_of_range& oore)
237 {
238 // Property value not found, netDelta unchanged
Matthew Barth0ce99d82017-06-22 15:07:29 -0500239 }
240 }
241 );
242 // Request speed decrease to occur on decrease interval
243 zone.requestSpeedDecrease(netDelta);
244 };
245}
246
Matthew Barth17d1fe22017-05-11 15:00:36 -0500247} // namespace action
248} // namespace control
249} // namespace fan
250} // namespace phosphor