blob: d33c366e8d44fc1038b724acd81705f0c7faf73f [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 Barth9ca60652020-02-10 13:01:08 -06007#include "utility.hpp"
Matthew Barth17d1fe22017-05-11 15:00:36 -05008
9namespace phosphor
10{
11namespace fan
12{
13namespace control
14{
15namespace action
16{
17
18/**
Matthew Barth2a646c52017-10-05 17:04:11 -050019 * @brief An action that wraps a list of actions with a timer
20 * @details Sets up a list of actions to be invoked when the defined timer
21 * expires (or for each expiration of a repeating timer).
22 *
23 * @param[in] tConf - Timer configuration parameters
24 * @param[in] action - List of actions to be called when the timer expires
25 *
26 * @return Action lambda function
27 * An Action function that creates a timer
28 */
29Action call_actions_based_on_timer(
William A. Kennington III122b8432018-10-30 18:39:21 -070030 TimerConf&& tConf,
Matthew Barth2a646c52017-10-05 17:04:11 -050031 std::vector<Action>&& actions);
32
33/**
Matthew Barth98726c42017-10-17 10:35:20 -050034 * @brief An action that sets the floor to the default fan floor speed
35 * @details Sets the fan floor to the defined default fan floor speed when a
36 * service associated to the given group has terminated. Once all services
37 * are functional and providing the sensors again, the fan floor is allowed
38 * to be set normally.
39 *
40 * @param[in] zone - Zone containing fans
41 * @param[in] group - Group of sensors to determine services' states
42 */
43void default_floor_on_missing_owner(Zone& zone, const Group& group);
44
45/**
Matthew Barth0decd1b2017-10-24 15:58:17 -050046 * @brief An action to set a speed when a service owner is missing
47 * @details Sets the fans to the given speed when any service owner associated
48 * to the group is missing. Once all services are functional and providing
49 * the event data again, active fan speed changes are allowed.
50 *
51 * @param[in] speed - Speed to set the zone to
52 *
53 * @return Action lambda function
54 * An Action function that sets the zone to the given speed if any service
55 * owners are missing.
56 */
57Action set_speed_on_missing_owner(uint64_t speed);
58
59/**
Matthew Barthb280bfa2017-09-15 09:56:50 -050060 * @brief An action to set the request speed base
61 * @details A new target speed is determined using a speed delta being added
62 * or subtracted, for increases or decrease respectively, from a base speed.
63 * This base speed defaults to be the current target speed or is set to a
64 * different base speed(i.e. the fans' tach feedback speed) to request a new
65 * target from.
66 *
67 * @param[in] zone - Zone containing fans
68 * @param[in] group - Group of sensors to determine base from
69 */
70void set_request_speed_base_with_max(Zone& zone, const Group& group);
71
72/**
Matthew Barth17d1fe22017-05-11 15:00:36 -050073 * @brief An action to set the speed on a zone
Matthew Barth861d77c2017-05-22 14:18:25 -050074 * @details The zone is held at the given speed when a defined number of
Matthew Barth17d1fe22017-05-11 15:00:36 -050075 * properties in the group are set to the given state
76 *
77 * @param[in] count - Number of properties
78 * @param[in] state - Value the property(s) needed to be set at
79 * @param[in] speed - Speed to set the zone to
80 *
81 * @return Lambda function
82 * A lambda function to set the zone speed when the number of properties
83 * within the group are at a certain value
84 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050085template <typename T>
86auto count_state_before_speed(size_t count, T&& state, uint64_t speed)
Matthew Barth17d1fe22017-05-11 15:00:36 -050087{
Matthew Barth9e741ed2017-06-02 16:29:09 -050088 return [count,
89 speed,
90 state = std::forward<T>(state)](auto& zone, auto& group)
Matthew Barth17d1fe22017-05-11 15:00:36 -050091 {
Matthew Barthe0f67c82018-05-08 15:47:12 -050092 size_t numAtState = 0;
93 for (auto& entry : group)
Matthew Barth17d1fe22017-05-11 15:00:36 -050094 {
Matthew Barthe0f67c82018-05-08 15:47:12 -050095 try
96 {
97 if (zone.template getPropertyValue<T>(
Matthew Barth146b7392018-03-08 16:17:58 -060098 std::get<pathPos>(entry),
99 std::get<intfPos>(entry),
100 std::get<propPos>(entry)) == state)
Matthew Barthe0f67c82018-05-08 15:47:12 -0500101 {
102 numAtState++;
103 }
104 }
105 catch (const std::out_of_range& oore)
106 {
107 // Default to property not equal when not found
108 }
109 if (numAtState >= count)
110 {
111 zone.setSpeed(speed);
112 break;
113 }
Matthew Barth17d1fe22017-05-11 15:00:36 -0500114 }
Matthew Barth60b00762017-08-15 13:39:06 -0500115 // Update group's fan control active allowed based on action results
116 zone.setActiveAllow(&group, !(numAtState >= count));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500117 };
118}
119
Matthew Barth4af419c2017-06-12 13:39:31 -0500120/**
121 * @brief An action to set the floor speed on a zone
122 * @details Based on the average of the defined sensor group values, the floor
123 * speed is selected from the first map key entry that the average sensor value
124 * is less than.
125 *
126 * @param[in] val_to_speed - Ordered map of sensor value-to-speed
127 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500128 * @return Action lambda function
129 * An Action function to set the zone's floor speed when the average of
Matthew Barth4af419c2017-06-12 13:39:31 -0500130 * property values within the group is below the lowest sensor value given
131 */
Matthew Barth9ca60652020-02-10 13:01:08 -0600132template <typename T>
Matthew Barthb280bfa2017-09-15 09:56:50 -0500133Action set_floor_from_average_sensor_value(
Matthew Barth9ca60652020-02-10 13:01:08 -0600134 std::map<T, uint64_t>&& val_to_speed)
135{
136 return [val_to_speed = std::move(val_to_speed)](control::Zone& zone,
137 const Group& group)
138 {
139 auto speed = zone.getDefFloor();
140 if (group.size() != 0)
141 {
142 auto count = 0;
143 auto sumValue = std::accumulate(
144 group.begin(),
145 group.end(),
146 0,
147 [&zone, &count](T sum, auto const& entry)
148 {
149 try
150 {
151 return sum +
152 zone.template getPropertyValue<T>(
153 std::get<pathPos>(entry),
154 std::get<intfPos>(entry),
155 std::get<propPos>(entry));
156 }
157 catch (const std::out_of_range& oore)
158 {
159 count++;
160 return sum;
161 }
162 });
163 if ((group.size() - count) > 0)
164 {
165 auto groupSize = static_cast<int64_t>(group.size());
166 auto avgValue = sumValue / (groupSize - count);
167 auto it = std::find_if(
168 val_to_speed.begin(),
169 val_to_speed.end(),
170 [&avgValue](auto const& entry)
171 {
172 return avgValue < entry.first;
173 }
174 );
175 if (it != std::end(val_to_speed))
176 {
177 speed = (*it).second;
178 }
179 }
180 }
181 zone.setFloor(speed);
182 };
183}
Matthew Barth4af419c2017-06-12 13:39:31 -0500184
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500185/**
186 * @brief An action to set the ceiling speed on a zone
Matthew Barthb280bfa2017-09-15 09:56:50 -0500187 * @details Based on the average of the defined sensor group values, the
188 * ceiling speed is selected from the map key transition point that the average
189 * sensor value falls within depending on the key values direction from what
190 * was previously read.
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500191 *
192 * @param[in] val_to_speed - Ordered map of sensor value-to-speed transitions
193 *
Matthew Barthb280bfa2017-09-15 09:56:50 -0500194 * @return Action lambda function
195 * An Action function to set the zone's ceiling speed when the average of
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500196 * property values within the group is above(increasing) or
197 * below(decreasing) the key transition point
198 */
Matthew Barth9ca60652020-02-10 13:01:08 -0600199template <typename T>
Matthew Barthb280bfa2017-09-15 09:56:50 -0500200Action set_ceiling_from_average_sensor_value(
Matthew Barth9ca60652020-02-10 13:01:08 -0600201 std::map<T, uint64_t>&& val_to_speed)
202{
203 return [val_to_speed = std::move(val_to_speed)](Zone& zone,
204 const Group& group)
205 {
206 auto speed = zone.getCeiling();
207 if (group.size() != 0)
208 {
209 auto count = 0;
210 auto sumValue = std::accumulate(
211 group.begin(),
212 group.end(),
213 0,
214 [&zone, &count](T sum, auto const& entry)
215 {
216 try
217 {
218 return sum +
219 zone.template getPropertyValue<T>(
220 std::get<pathPos>(entry),
221 std::get<intfPos>(entry),
222 std::get<propPos>(entry));
223 }
224 catch (const std::out_of_range& oore)
225 {
226 count++;
227 return sum;
228 }
229 });
230 if ((group.size() - count) > 0)
231 {
232 auto groupSize = static_cast<int64_t>(group.size());
233 auto avgValue = sumValue / (groupSize - count);
234 auto prevValue = zone.swapCeilingKeyValue(avgValue);
235 if (avgValue != prevValue)
236 {// Only check if previous and new values differ
237 if (avgValue < prevValue)
238 {// Value is decreasing from previous
239 for (auto it = val_to_speed.rbegin();
240 it != val_to_speed.rend();
241 ++it)
242 {
243 if (it == val_to_speed.rbegin() &&
244 avgValue >= it->first)
245 {
246 // Value is at/above last map key, set
247 // ceiling speed to the last map key's value
248 speed = it->second;
249 break;
250 }
251 else if (std::next(it, 1) == val_to_speed.rend() &&
252 avgValue <= it->first)
253 {
254 // Value is at/below first map key, set
255 // ceiling speed to the first map key's value
256 speed = it->second;
257 break;
258 }
259 if (avgValue < it->first &&
260 it->first <= prevValue)
261 {
262 // Value decreased & transitioned across
263 // a map key, update ceiling speed to this
264 // map key's value when new value is below
265 // map's key and the key is at/below the
266 // previous value
267 speed = it->second;
268 }
269 }
270 }
271 else
272 {// Value is increasing from previous
273 for (auto it = val_to_speed.begin();
274 it != val_to_speed.end();
275 ++it)
276 {
277 if (it == val_to_speed.begin() &&
278 avgValue <= it->first)
279 {
280 // Value is at/below first map key, set
281 // ceiling speed to the first map key's value
282 speed = it->second;
283 break;
284 }
285 else if (std::next(it, 1) == val_to_speed.end() &&
286 avgValue >= it->first)
287 {
288 // Value is at/above last map key, set
289 // ceiling speed to the last map key's value
290 speed = it->second;
291 break;
292 }
293 if (avgValue > it->first &&
294 it->first >= prevValue)
295 {
296 // Value increased & transitioned across
297 // a map key, update ceiling speed to this
298 // map key's value when new value is above
299 // map's key and the key is at/above the
300 // previous value
301 speed = it->second;
302 }
303 }
304 }
305 }
306 }
307 }
308 zone.setCeiling(speed);
309 };
310}
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500311
Matthew Barth24623522017-06-21 14:09:57 -0500312/**
313 * @brief An action to set the speed increase delta and request speed change
314 * @details Provides the ability to determine what the net increase delta the
315 * zone's fan speeds should be updated by from their current target speed and
316 * request that new target speed.
317 *
318 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500319 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth24623522017-06-21 14:09:57 -0500320 * @param[in] speedDelta - Speed delta of the group
321 *
322 * @return Lambda function
323 * A lambda function that determines the net increase delta and requests
324 * a new target speed with that increase for the zone.
325 */
326template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500327auto set_net_increase_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth24623522017-06-21 14:09:57 -0500328{
329 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500330 factor = std::forward<T>(factor),
Matthew Barth24623522017-06-21 14:09:57 -0500331 state = std::forward<T>(state)](auto& zone, auto& group)
332 {
333 auto netDelta = zone.getIncSpeedDelta();
334 std::for_each(
335 group.begin(),
336 group.end(),
Matthew Barth172f3932017-08-14 11:07:46 -0500337 [&zone, &state, &factor, &speedDelta, &netDelta](
Matthew Barthbc651602017-08-10 16:59:43 -0500338 auto const& entry)
Matthew Barth24623522017-06-21 14:09:57 -0500339 {
Matthew Barthbc651602017-08-10 16:59:43 -0500340 try
Matthew Barth24623522017-06-21 14:09:57 -0500341 {
Matthew Barthbc651602017-08-10 16:59:43 -0500342 T value = zone.template getPropertyValue<T>(
Matthew Barth146b7392018-03-08 16:17:58 -0600343 std::get<pathPos>(entry),
344 std::get<intfPos>(entry),
345 std::get<propPos>(entry));
Matthew Barthbc651602017-08-10 16:59:43 -0500346 // TODO openbmc/phosphor-fan-presence#7 - Support possible
347 // state types for comparison
348 if (value >= state)
349 {
Matthew Barth172f3932017-08-14 11:07:46 -0500350 // Increase by at least a single delta(factor)
Matthew Barthbc651602017-08-10 16:59:43 -0500351 // to attempt bringing under 'state'
Matthew Barth172f3932017-08-14 11:07:46 -0500352 auto delta = std::max(
353 (value - state),
354 factor);
355 // Increase is the factor applied to the
356 // difference times the given speed delta
357 netDelta = std::max(
358 netDelta,
Matthew Barth9ca60652020-02-10 13:01:08 -0600359 static_cast<uint64_t>((delta/factor) * speedDelta));
Matthew Barthbc651602017-08-10 16:59:43 -0500360 }
361 }
362 catch (const std::out_of_range& oore)
363 {
364 // Property value not found, netDelta unchanged
Matthew Barth24623522017-06-21 14:09:57 -0500365 }
366 }
367 );
Matthew Barth240397b2017-06-22 11:23:30 -0500368 // Request speed change for target speed update
369 zone.requestSpeedIncrease(netDelta);
Matthew Barth24623522017-06-21 14:09:57 -0500370 };
371}
372
Matthew Barth0ce99d82017-06-22 15:07:29 -0500373/**
374 * @brief An action to set the speed decrease delta and request speed change
375 * @details Provides the ability to determine what the net decrease delta each
376 * zone's fan speeds should be updated by from their current target speed, and
377 * request that speed change occur on the next decrease interval.
378 *
379 * @param[in] state - State to compare the group's property value to
Matthew Barth172f3932017-08-14 11:07:46 -0500380 * @param[in] factor - Factor to apply to the calculated net delta
Matthew Barth0ce99d82017-06-22 15:07:29 -0500381 * @param[in] speedDelta - Speed delta of the group
382 *
383 * @return Lambda function
384 * A lambda function that determines the net decrease delta and requests
385 * a new target speed with that decrease for the zone.
386 */
387template <typename T>
Matthew Barth172f3932017-08-14 11:07:46 -0500388auto set_net_decrease_speed(T&& state, T&& factor, uint64_t speedDelta)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500389{
390 return [speedDelta,
Matthew Barth172f3932017-08-14 11:07:46 -0500391 factor = std::forward<T>(factor),
Matthew Barth0ce99d82017-06-22 15:07:29 -0500392 state = std::forward<T>(state)](auto& zone, auto& group)
393 {
394 auto netDelta = zone.getDecSpeedDelta();
Matthew Barthe4338cd2017-12-14 11:14:30 -0600395 for (auto& entry : group)
396 {
397 try
Matthew Barth0ce99d82017-06-22 15:07:29 -0500398 {
Matthew Barthe4338cd2017-12-14 11:14:30 -0600399 T value = zone.template getPropertyValue<T>(
Matthew Barth146b7392018-03-08 16:17:58 -0600400 std::get<pathPos>(entry),
401 std::get<intfPos>(entry),
402 std::get<propPos>(entry));
Matthew Barthe4338cd2017-12-14 11:14:30 -0600403 // TODO openbmc/phosphor-fan-presence#7 - Support possible
404 // state types for comparison
405 if (value < state)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500406 {
Matthew Barthe4338cd2017-12-14 11:14:30 -0600407 if (netDelta == 0)
Matthew Barth0ce99d82017-06-22 15:07:29 -0500408 {
Matthew Barthe4338cd2017-12-14 11:14:30 -0600409 netDelta = ((state - value)/factor) * speedDelta;
410 }
411 else
412 {
413 // Decrease is the factor applied to the
414 // difference times the given speed delta
415 netDelta = std::min(
416 netDelta,
Matthew Barth9ca60652020-02-10 13:01:08 -0600417 static_cast<uint64_t>(
418 ((state - value)/factor) * speedDelta));
Matthew Barth0ce99d82017-06-22 15:07:29 -0500419 }
Matthew Barthbc651602017-08-10 16:59:43 -0500420 }
Matthew Barthe4338cd2017-12-14 11:14:30 -0600421 else
Matthew Barthbc651602017-08-10 16:59:43 -0500422 {
Matthew Barthe4338cd2017-12-14 11:14:30 -0600423 // No decrease allowed for this group
424 netDelta = 0;
425 break;
Matthew Barth0ce99d82017-06-22 15:07:29 -0500426 }
427 }
Matthew Barthe4338cd2017-12-14 11:14:30 -0600428 catch (const std::out_of_range& oore)
429 {
430 // Property value not found, netDelta unchanged
431 }
432 }
433 // Update group's decrease allowed state
434 zone.setDecreaseAllow(&group, !(netDelta == 0));
Matthew Barth0ce99d82017-06-22 15:07:29 -0500435 // Request speed decrease to occur on decrease interval
436 zone.requestSpeedDecrease(netDelta);
437 };
438}
439
Matthew Barthc410dda2019-01-11 16:31:13 -0600440/**
441 * @brief An action to use an alternate set of events
442 * @details Provides the ability to replace a default set of events with an
443 * alternate set of events based on all members of a group being at a specified
444 * state. When any member of the group no longer matches the provided state,
445 * the alternate set of events are replaced with the defaults.
446 *
447 * @param[in] state - State to compare the group's property value to
448 * @param[in] defEvents - The default set of events
449 * @param[in] altEvents - The alternate set of events
450 *
451 * @return Lambda function
452 * A lambda function that checks all group members are at a specified state
453 * and replacing the default set of events with an alternate set of events.
454 */
455template <typename T>
456auto use_alternate_events_on_state(T&& state,
457 std::vector<SetSpeedEvent>&& defEvents,
458 std::vector<SetSpeedEvent>&& altEvents)
459{
460 return [state = std::forward<T>(state),
461 defEvents = std::move(defEvents),
462 altEvents = std::move(altEvents)](auto& zone, auto& group)
463 {
464 // Compare all group entries to the state
465 auto useAlt = std::all_of(
466 group.begin(),
467 group.end(),
468 [&zone, &state](auto const& entry)
469 {
470 try
471 {
472 return zone.template getPropertyValue<T>(
Matthew Barth146b7392018-03-08 16:17:58 -0600473 std::get<pathPos>(entry),
474 std::get<intfPos>(entry),
475 std::get<propPos>(entry)) == state;
Matthew Barthc410dda2019-01-11 16:31:13 -0600476 }
477 catch (const std::out_of_range& oore)
478 {
479 // Default to property not equal when not found
480 return false;
481 }
482 });
483
484 const std::vector<SetSpeedEvent> *rmEvents = &altEvents;
485 const std::vector<SetSpeedEvent> *initEvents = &defEvents;
486
487 if (useAlt)
488 {
489 rmEvents = &defEvents;
490 initEvents = &altEvents;
491 }
492
493 // Remove events
494 std::for_each(
495 rmEvents->begin(),
496 rmEvents->end(),
497 [&zone](auto const& entry)
498 {
499 zone.removeEvent(entry);
500 });
501 // Init events
502 std::for_each(
503 initEvents->begin(),
504 initEvents->end(),
505 [&zone](auto const& entry)
506 {
507 zone.initEvent(entry);
508 });
509 };
510}
511
Matthew Barth014f07c2019-05-30 09:55:42 -0500512/**
513 * @brief An action to set the floor speed on a zone
514 * @details Using sensor group values that are within a defined range, the
515 * floor speed is selected from the first map key entry that the median
516 * sensor value is less than where 3 or more sensor group values are valid.
517 * In the case where less than 3 sensor values are valid, use the highest
518 * sensor group value and default the floor speed when 0 sensor group values
519 * are valid.
520 *
521 * @param[in] lowerBound - Lowest allowed sensor value to be valid
522 * @param[in] upperBound - Highest allowed sensor value to be valid
523 * @param[in] valueToSpeed - Ordered map of sensor value-to-speed
524 *
525 * @return Action lambda function
526 * An Action function to set the zone's floor speed from a resulting group
527 * of valid sensor values based on their highest value or median.
528 */
Matthew Barth9ca60652020-02-10 13:01:08 -0600529template <typename T>
Matthew Barth014f07c2019-05-30 09:55:42 -0500530Action set_floor_from_median_sensor_value(
Matthew Barth9ca60652020-02-10 13:01:08 -0600531 T&& lowerBound,
532 T&& upperBound,
533 std::map<T, uint64_t>&& valueToSpeed)
534{
535 return [lowerBound = std::forward<T>(lowerBound),
536 upperBound = std::forward<T>(upperBound),
537 valueToSpeed = std::move(valueToSpeed)](control::Zone& zone,
538 const Group& group)
539 {
540 auto speed = zone.getDefFloor();
541 if (group.size() != 0)
542 {
543 std::vector<T> validValues;
544 for (auto const& member : group)
545 {
546 try
547 {
548 auto value = zone.template getPropertyValue<T>(
549 std::get<pathPos>(member),
550 std::get<intfPos>(member),
551 std::get<propPos>(member));
552 if (value == std::clamp(value, lowerBound, upperBound))
553 {
554 // Sensor value is valid
555 validValues.emplace_back(value);
556 }
557 }
558 catch (const std::out_of_range& oore)
559 {
560 continue;
561 }
562 }
563
564 if (!validValues.empty())
565 {
566 auto median = validValues.front();
567 // Get the determined median value
568 if (validValues.size() == 2)
569 {
570 // For 2 values, use the highest instead of the average
571 // for a thermally safe floor
572 median = *std::max_element(validValues.begin(),
573 validValues.end());
574 }
575 else if (validValues.size() > 2)
576 {
577 median = utility::getMedian(validValues);
578 }
579
580 // Use determined median sensor value to find floor speed
581 auto it = std::find_if(
582 valueToSpeed.begin(),
583 valueToSpeed.end(),
584 [&median](auto const& entry)
585 {
586 return median < entry.first;
587 }
588 );
589 if (it != std::end(valueToSpeed))
590 {
591 speed = (*it).second;
592 }
593 }
594 }
595 zone.setFloor(speed);
596 };
597}
Matthew Barth014f07c2019-05-30 09:55:42 -0500598
Matthew Barth8d06a832019-10-02 14:43:39 -0500599/**
600 * @brief An action to update the default floor speed
601 * @details Provides the ability to update the default fan floor speed when
602 * all of the group members property values match the value given
603 *
604 * @param[in] state - State to compare the group's property value to
605 * @param[in] speed - Speed to set the default fan floor to
606 *
607 * @return Lambda function
608 * A lambda function that checks all group members are at a specified state
609 * and updates the default fan floor speed.
610 */
611template <typename T>
612auto update_default_floor(T&& state, uint64_t speed)
613{
614 return [speed, state = std::forward<T>(state)](auto& zone, auto& group)
615 {
616 auto updateDefFloor = std::all_of(
617 group.begin(),
618 group.end(),
619 [&zone, &state](auto const& entry)
620 {
621 try
622 {
623 return zone.template getPropertyValue<T>(
624 std::get<pathPos>(entry),
625 std::get<intfPos>(entry),
626 std::get<propPos>(entry)) == state;
627 }
628 catch (const std::out_of_range& oore)
629 {
630 // Default to property not equal when not found
631 return false;
632 }
633 });
634
635 if (!updateDefFloor)
636 {
637 // Do not update the default floor
638 return;
639 }
640
641 // Set/update the default floor of the zone
642 zone.setDefFloor(speed);
643 };
644}
645
Matthew Barth799cdf72019-10-08 15:00:10 -0500646/**
647 * @brief An action to use a set of events
648 * @details Provides the ability to use a set of events when all members of
649 * a group are at a specified state. When any member of the group no longer
650 * matches the provided state the set of events are removed.
651 *
652 * @param[in] state - State to compare the group's property value to
653 * @param[in] events - The set of events
654 *
655 * @return Lambda function
656 * A lambda function that checks all group members are at a specified state
657 * and initializes the set of events, otherwise removes them.
658 */
659template <typename T>
660auto use_events_on_state(T&& state,
661 std::vector<SetSpeedEvent>&& events)
662{
663 return [state = std::forward<T>(state),
664 events = std::move(events)](auto& zone, auto& group)
665 {
666 // Compare all group entries to the state
667 auto useEvents = std::all_of(
668 group.begin(),
669 group.end(),
670 [&zone, &state](auto const& entry)
671 {
672 try
673 {
674 return zone.template getPropertyValue<T>(
675 std::get<pathPos>(entry),
676 std::get<intfPos>(entry),
677 std::get<propPos>(entry)) == state;
678 }
679 catch (const std::out_of_range& oore)
680 {
681 // Default to property not equal when not found
682 return false;
683 }
684 });
685
686 if (useEvents)
687 {
688 // Init events
689 std::for_each(
690 events.begin(),
691 events.end(),
692 [&zone](auto const& entry)
693 {
694 zone.initEvent(entry);
695 });
696 }
697 else
698 {
699 // Remove events
700 std::for_each(
701 events.begin(),
702 events.end(),
703 [&zone](auto const& entry)
704 {
705 zone.removeEvent(entry);
706 });
707 }
708 };
709}
710
Matthew Barth17d1fe22017-05-11 15:00:36 -0500711} // namespace action
712} // namespace control
713} // namespace fan
714} // namespace phosphor