blob: 55c8af883bd675d307cf2a020b0d634c1acefea9 [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 Barth98726c42017-10-17 10:35:20 -050033 * @brief An action that sets the floor to the default fan floor speed
34 * @details Sets the fan floor to the defined default fan floor speed when a
35 * service associated to the given group has terminated. Once all services
36 * are functional and providing the sensors again, the fan floor is allowed
37 * to be set normally.
38 *
39 * @param[in] zone - Zone containing fans
40 * @param[in] group - Group of sensors to determine services' states
41 */
42void default_floor_on_missing_owner(Zone& zone, const Group& group);
43
44/**
Matthew Barth0decd1b2017-10-24 15:58:17 -050045 * @brief An action to set a speed when a service owner is missing
46 * @details Sets the fans to the given speed when any service owner associated
47 * to the group is missing. Once all services are functional and providing
48 * the event data again, active fan speed changes are allowed.
49 *
50 * @param[in] speed - Speed to set the zone to
51 *
52 * @return Action lambda function
53 * An Action function that sets the zone to the given speed if any service
54 * owners are missing.
55 */
56Action set_speed_on_missing_owner(uint64_t speed);
57
58/**
Matthew Barthb280bfa2017-09-15 09:56:50 -050059 * @brief An action to set the request speed base
60 * @details A new target speed is determined using a speed delta being added
61 * or subtracted, for increases or decrease respectively, from a base speed.
62 * This base speed defaults to be the current target speed or is set to a
63 * different base speed(i.e. the fans' tach feedback speed) to request a new
64 * target from.
65 *
66 * @param[in] zone - Zone containing fans
67 * @param[in] group - Group of sensors to determine base from
68 */
69void set_request_speed_base_with_max(Zone& zone, const Group& group);
70
71/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050072 * @brief An action to set the speed on a zone
Matthew Barth861d77c2017-05-22 14:18:25 -050073 * @details The zone is held at the given speed when a defined number of
Matthew Barth17d1fe22017-05-11 15:00:36 -050074 * properties in the group are set to the given state
75 *
76 * @param[in] count - Number of properties
77 * @param[in] state - Value the property(s) needed to be set at
78 * @param[in] speed - Speed to set the zone to
79 *
80 * @return Lambda function
81 * A lambda function to set the zone speed when the number of properties
82 * within the group are at a certain value
83 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050084template <typename T>
85auto count_state_before_speed(size_t count, T&& state, uint64_t speed)
Matthew Barth17d1fe22017-05-11 15:00:36 -050086{
Matthew Barth9e741ed2017-06-02 16:29:09 -050087 return [count,
88 speed,
89 state = std::forward<T>(state)](auto& zone, auto& group)
Matthew Barth17d1fe22017-05-11 15:00:36 -050090 {
91 size_t numAtState = std::count_if(
92 group.begin(),
93 group.end(),
94 [&zone, &state](auto const& entry)
95 {
Matthew Barthbc651602017-08-10 16:59:43 -050096 try
97 {
98 return zone.template getPropertyValue<T>(
99 entry.first,
100 std::get<intfPos>(entry.second),
101 std::get<propPos>(entry.second)) == state;
102 }
103 catch (const std::out_of_range& oore)
104 {
105 // Default to property not equal when not found
106 return false;
107 }
Matthew Barth17d1fe22017-05-11 15:00:36 -0500108 });
Matthew Barth17d1fe22017-05-11 15:00:36 -0500109 if (numAtState >= count)
110 {
111 zone.setSpeed(speed);
112 }
Matthew Barth60b00762017-08-15 13:39:06 -0500113 // Update group's fan control active allowed based on action results
114 zone.setActiveAllow(&group, !(numAtState >= count));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500115 };
116}
117
Matthew Barth4af419c2017-06-12 13:39:31 -0500118/**
119 * @brief An action to set the floor speed on a zone
120 * @details Based on the average of the defined sensor group values, the floor
121 * speed is selected from the first map key entry that the average sensor value
122 * is less than.
123 *
124 * @param[in] val_to_speed - Ordered map of sensor value-to-speed
125 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500126 * @return Action lambda function
127 * An Action function to set the zone's floor speed when the average of
Matthew Barth4af419c2017-06-12 13:39:31 -0500128 * property values within the group is below the lowest sensor value given
129 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500130Action set_floor_from_average_sensor_value(
131 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barth4af419c2017-06-12 13:39:31 -0500132
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500133/**
134 * @brief An action to set the ceiling speed on a zone
Matthew Barthb280bfa2017-09-15 09:56:50 -0500135 * @details Based on the average of the defined sensor group values, the
136 * ceiling speed is selected from the map key transition point that the average
137 * sensor value falls within depending on the key values direction from what
138 * was previously read.
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500139 *
140 * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions
141 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500142 * @return Action lambda function
143 * An Action function to set the zone's ceiling speed when the average of
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500144 * property values within the group is above(increasing) or
145 * below(decreasing) the key transition point
146 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500147Action set_ceiling_from_average_sensor_value(
148 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500149
Matthew Barth24623522017-06-21 14:09:57 -0500150/**
151 * @brief An action to set the speed increase delta and request speed change
152 * @details Provides the ability to determine what the net increase delta the
153 * zone's fan speeds should be updated by from their current target speed and
154 * request that new target speed.
155 *
156 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500157 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth24623522017-06-21 14:09:57 -0500158 * @param[in] speedDelta - Speed delta of the group
159 *
160 * @return Lambda function
161 * A lambda function that determines the net increase delta and requests
162 * a new target speed with that increase for the zone.
163 */
164template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500165auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth24623522017-06-21 14:09:57 -0500166{
167 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500168 factor = std::forward<T>(factor),
Matthew Barth24623522017-06-21 14:09:57 -0500169 state = std::forward<T>(state)](auto& zone, auto& group)
170 {
171 auto netDelta = zone.getIncSpeedDelta();
172 std::for_each(
173 group.begin(),
174 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500175 [&zone, &state, &factor, &speedDelta, &netDelta](
Matthew Barthbc651602017-08-10 16:59:43 -0500176 auto const& entry)
Matthew Barth24623522017-06-21 14:09:57 -0500177 {
Matthew Barthbc651602017-08-10 16:59:43 -0500178 try
Matthew Barth24623522017-06-21 14:09:57 -0500179 {
Matthew Barthbc651602017-08-10 16:59:43 -0500180 T value = zone.template getPropertyValue<T>(
181 entry.first,
182 std::get<intfPos>(entry.second),
183 std::get<propPos>(entry.second));
184 // TODO openbmc/phosphor-fan-presence#7 - Support possible
185 // state types for comparison
186 if (value >= state)
187 {
Matthew Barth172f3932017-08-14 11:07:46 -0500188 // Increase by at least a single delta(factor)
Matthew Barthbc651602017-08-10 16:59:43 -0500189 // to attempt bringing under 'state'
Matthew Barth172f3932017-08-14 11:07:46 -0500190 auto delta = std::max(
191 (value - state),
192 factor);
193 // Increase is the factor applied to the
194 // difference times the given speed delta
195 netDelta = std::max(
196 netDelta,
197 (delta/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500198 }
199 }
200 catch (const std::out_of_range& oore)
201 {
202 // Property value not found, netDelta unchanged
Matthew Barth24623522017-06-21 14:09:57 -0500203 }
204 }
205 );
Matthew Barth240397b2017-06-22 11:23:30 -0500206 // Request speed change for target speed update
207 zone.requestSpeedIncrease(netDelta);
Matthew Barth24623522017-06-21 14:09:57 -0500208 };
209}
210
Matthew Barth0ce99d82017-06-22 15:07:29 -0500211/**
212 * @brief An action to set the speed decrease delta and request speed change
213 * @details Provides the ability to determine what the net decrease delta each
214 * zone's fan speeds should be updated by from their current target speed, and
215 * request that speed change occur on the next decrease interval.
216 *
217 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500218 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth0ce99d82017-06-22 15:07:29 -0500219 * @param[in] speedDelta - Speed delta of the group
220 *
221 * @return Lambda function
222 * A lambda function that determines the net decrease delta and requests
223 * a new target speed with that decrease for the zone.
224 */
225template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500226auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500227{
228 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500229 factor = std::forward<T>(factor),
Matthew Barth0ce99d82017-06-22 15:07:29 -0500230 state = std::forward<T>(state)](auto& zone, auto& group)
231 {
232 auto netDelta = zone.getDecSpeedDelta();
233 std::for_each(
234 group.begin(),
235 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500236 [&zone, &state, &factor, &speedDelta, &netDelta](auto const& entry)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500237 {
Matthew Barthbc651602017-08-10 16:59:43 -0500238 try
Matthew Barth0ce99d82017-06-22 15:07:29 -0500239 {
Matthew Barthbc651602017-08-10 16:59:43 -0500240 T value = zone.template getPropertyValue<T>(
241 entry.first,
242 std::get<intfPos>(entry.second),
243 std::get<propPos>(entry.second));
244 // TODO openbmc/phosphor-fan-presence#7 - Support possible
245 // state types for comparison
246 if (value < state)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500247 {
Matthew Barthbc651602017-08-10 16:59:43 -0500248 if (netDelta == 0)
249 {
Matthew Barth172f3932017-08-14 11:07:46 -0500250 netDelta = ((state - value)/factor) * speedDelta;
Matthew Barthbc651602017-08-10 16:59:43 -0500251 }
252 else
253 {
Matthew Barth172f3932017-08-14 11:07:46 -0500254 // Decrease is the factor applied to the
255 // difference times the given speed delta
256 netDelta = std::min(
257 netDelta,
258 ((state - value)/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500259 }
Matthew Barth0ce99d82017-06-22 15:07:29 -0500260 }
Matthew Barthbc651602017-08-10 16:59:43 -0500261 }
262 catch (const std::out_of_range& oore)
263 {
264 // Property value not found, netDelta unchanged
Matthew Barth0ce99d82017-06-22 15:07:29 -0500265 }
266 }
267 );
268 // Request speed decrease to occur on decrease interval
269 zone.requestSpeedDecrease(netDelta);
270 };
271}
272
Matthew Barth17d1fe22017-05-11 15:00:36 -0500273} // namespace action
274} // namespace control
275} // namespace fan
276} // namespace phosphor