blob: 4d2c5c3e562fc1f848ccf30e2a920ca603ff74e2 [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 Barthb280bfa2017-09-15 09:56:50 -050045 * @brief An action to set the request speed base
46 * @details A new target speed is determined using a speed delta being added
47 * or subtracted, for increases or decrease respectively, from a base speed.
48 * This base speed defaults to be the current target speed or is set to a
49 * different base speed(i.e. the fans' tach feedback speed) to request a new
50 * target from.
51 *
52 * @param[in] zone - Zone containing fans
53 * @param[in] group - Group of sensors to determine base from
54 */
55void set_request_speed_base_with_max(Zone& zone, const Group& group);
56
57/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050058 * @brief An action to set the speed on a zone
Matthew Barth861d77c2017-05-22 14:18:25 -050059 * @details The zone is held at the given speed when a defined number of
Matthew Barth17d1fe22017-05-11 15:00:36 -050060 * properties in the group are set to the given state
61 *
62 * @param[in] count - Number of properties
63 * @param[in] state - Value the property(s) needed to be set at
64 * @param[in] speed - Speed to set the zone to
65 *
66 * @return Lambda function
67 * A lambda function to set the zone speed when the number of properties
68 * within the group are at a certain value
69 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050070template <typename T>
71auto count_state_before_speed(size_t count, T&& state, uint64_t speed)
Matthew Barth17d1fe22017-05-11 15:00:36 -050072{
Matthew Barth9e741ed2017-06-02 16:29:09 -050073 return [count,
74 speed,
75 state = std::forward<T>(state)](auto& zone, auto& group)
Matthew Barth17d1fe22017-05-11 15:00:36 -050076 {
77 size_t numAtState = std::count_if(
78 group.begin(),
79 group.end(),
80 [&zone, &state](auto const& entry)
81 {
Matthew Barthbc651602017-08-10 16:59:43 -050082 try
83 {
84 return zone.template getPropertyValue<T>(
85 entry.first,
86 std::get<intfPos>(entry.second),
87 std::get<propPos>(entry.second)) == state;
88 }
89 catch (const std::out_of_range& oore)
90 {
91 // Default to property not equal when not found
92 return false;
93 }
Matthew Barth17d1fe22017-05-11 15:00:36 -050094 });
Matthew Barth17d1fe22017-05-11 15:00:36 -050095 if (numAtState >= count)
96 {
97 zone.setSpeed(speed);
98 }
Matthew Barth60b00762017-08-15 13:39:06 -050099 // Update group's fan control active allowed based on action results
100 zone.setActiveAllow(&group, !(numAtState >= count));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500101 };
102}
103
Matthew Barth4af419c2017-06-12 13:39:31 -0500104/**
105 * @brief An action to set the floor speed on a zone
106 * @details Based on the average of the defined sensor group values, the floor
107 * speed is selected from the first map key entry that the average sensor value
108 * is less than.
109 *
110 * @param[in] val_to_speed - Ordered map of sensor value-to-speed
111 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500112 * @return Action lambda function
113 * An Action function to set the zone's floor speed when the average of
Matthew Barth4af419c2017-06-12 13:39:31 -0500114 * property values within the group is below the lowest sensor value given
115 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500116Action set_floor_from_average_sensor_value(
117 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barth4af419c2017-06-12 13:39:31 -0500118
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500119/**
120 * @brief An action to set the ceiling speed on a zone
Matthew Barthb280bfa2017-09-15 09:56:50 -0500121 * @details Based on the average of the defined sensor group values, the
122 * ceiling speed is selected from the map key transition point that the average
123 * sensor value falls within depending on the key values direction from what
124 * was previously read.
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500125 *
126 * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions
127 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500128 * @return Action lambda function
129 * An Action function to set the zone's ceiling speed when the average of
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500130 * property values within the group is above(increasing) or
131 * below(decreasing) the key transition point
132 */
Matthew Barthb280bfa2017-09-15 09:56:50 -0500133Action set_ceiling_from_average_sensor_value(
134 std::map<int64_t, uint64_t>&& val_to_speed);
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500135
Matthew Barth24623522017-06-21 14:09:57 -0500136/**
137 * @brief An action to set the speed increase delta and request speed change
138 * @details Provides the ability to determine what the net increase delta the
139 * zone's fan speeds should be updated by from their current target speed and
140 * request that new target speed.
141 *
142 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500143 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth24623522017-06-21 14:09:57 -0500144 * @param[in] speedDelta - Speed delta of the group
145 *
146 * @return Lambda function
147 * A lambda function that determines the net increase delta and requests
148 * a new target speed with that increase for the zone.
149 */
150template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500151auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth24623522017-06-21 14:09:57 -0500152{
153 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500154 factor = std::forward<T>(factor),
Matthew Barth24623522017-06-21 14:09:57 -0500155 state = std::forward<T>(state)](auto& zone, auto& group)
156 {
157 auto netDelta = zone.getIncSpeedDelta();
158 std::for_each(
159 group.begin(),
160 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500161 [&zone, &state, &factor, &speedDelta, &netDelta](
Matthew Barthbc651602017-08-10 16:59:43 -0500162 auto const& entry)
Matthew Barth24623522017-06-21 14:09:57 -0500163 {
Matthew Barthbc651602017-08-10 16:59:43 -0500164 try
Matthew Barth24623522017-06-21 14:09:57 -0500165 {
Matthew Barthbc651602017-08-10 16:59:43 -0500166 T value = zone.template getPropertyValue<T>(
167 entry.first,
168 std::get<intfPos>(entry.second),
169 std::get<propPos>(entry.second));
170 // TODO openbmc/phosphor-fan-presence#7 - Support possible
171 // state types for comparison
172 if (value >= state)
173 {
Matthew Barth172f3932017-08-14 11:07:46 -0500174 // Increase by at least a single delta(factor)
Matthew Barthbc651602017-08-10 16:59:43 -0500175 // to attempt bringing under 'state'
Matthew Barth172f3932017-08-14 11:07:46 -0500176 auto delta = std::max(
177 (value - state),
178 factor);
179 // Increase is the factor applied to the
180 // difference times the given speed delta
181 netDelta = std::max(
182 netDelta,
183 (delta/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500184 }
185 }
186 catch (const std::out_of_range& oore)
187 {
188 // Property value not found, netDelta unchanged
Matthew Barth24623522017-06-21 14:09:57 -0500189 }
190 }
191 );
Matthew Barth240397b2017-06-22 11:23:30 -0500192 // Request speed change for target speed update
193 zone.requestSpeedIncrease(netDelta);
Matthew Barth24623522017-06-21 14:09:57 -0500194 };
195}
196
Matthew Barth0ce99d82017-06-22 15:07:29 -0500197/**
198 * @brief An action to set the speed decrease delta and request speed change
199 * @details Provides the ability to determine what the net decrease delta each
200 * zone's fan speeds should be updated by from their current target speed, and
201 * request that speed change occur on the next decrease interval.
202 *
203 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500204 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth0ce99d82017-06-22 15:07:29 -0500205 * @param[in] speedDelta - Speed delta of the group
206 *
207 * @return Lambda function
208 * A lambda function that determines the net decrease delta and requests
209 * a new target speed with that decrease for the zone.
210 */
211template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500212auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500213{
214 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500215 factor = std::forward<T>(factor),
Matthew Barth0ce99d82017-06-22 15:07:29 -0500216 state = std::forward<T>(state)](auto& zone, auto& group)
217 {
218 auto netDelta = zone.getDecSpeedDelta();
219 std::for_each(
220 group.begin(),
221 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500222 [&zone, &state, &factor, &speedDelta, &netDelta](auto const& entry)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500223 {
Matthew Barthbc651602017-08-10 16:59:43 -0500224 try
Matthew Barth0ce99d82017-06-22 15:07:29 -0500225 {
Matthew Barthbc651602017-08-10 16:59:43 -0500226 T value = zone.template getPropertyValue<T>(
227 entry.first,
228 std::get<intfPos>(entry.second),
229 std::get<propPos>(entry.second));
230 // TODO openbmc/phosphor-fan-presence#7 - Support possible
231 // state types for comparison
232 if (value < state)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500233 {
Matthew Barthbc651602017-08-10 16:59:43 -0500234 if (netDelta == 0)
235 {
Matthew Barth172f3932017-08-14 11:07:46 -0500236 netDelta = ((state - value)/factor) * speedDelta;
Matthew Barthbc651602017-08-10 16:59:43 -0500237 }
238 else
239 {
Matthew Barth172f3932017-08-14 11:07:46 -0500240 // Decrease is the factor applied to the
241 // difference times the given speed delta
242 netDelta = std::min(
243 netDelta,
244 ((state - value)/factor) * speedDelta);
Matthew Barthbc651602017-08-10 16:59:43 -0500245 }
Matthew Barth0ce99d82017-06-22 15:07:29 -0500246 }
Matthew Barthbc651602017-08-10 16:59:43 -0500247 }
248 catch (const std::out_of_range& oore)
249 {
250 // Property value not found, netDelta unchanged
Matthew Barth0ce99d82017-06-22 15:07:29 -0500251 }
252 }
253 );
254 // Request speed decrease to occur on decrease interval
255 zone.requestSpeedDecrease(netDelta);
256 };
257}
258
Matthew Barth17d1fe22017-05-11 15:00:36 -0500259} // namespace action
260} // namespace control
261} // namespace fan
262} // namespace phosphor