1 #pragma once
2 
3 #include <algorithm>
4 #include <phosphor-logging/log.hpp>
5 
6 namespace phosphor
7 {
8 namespace fan
9 {
10 namespace control
11 {
12 namespace precondition
13 {
14 
15 using namespace phosphor::logging;
16 
17 /**
18  * @brief A precondition to compare a group of property values and
19  * subscribe/unsubscribe a set speed event group
20  * @details Compares each entry within the precondition group to a given value
21  * that when each entry's property value matches the given value, the set speed
22  * event is then initialized. At any point a precondition entry's value no
23  * longer matches, the set speed event is removed from being active and fans
24  * are set to full speed.
25  *
26  * @param[in] pg - Precondition property group of property values
27  * @param[in] sse - Set speed event definition
28  *
29  * @return Lambda function
30  *     A lambda function to compare precondition property value states
31  *     and either subscribe or unsubscribe a set speed event group.
32  */
33 auto property_states_match(std::vector<PrecondGroup>&& pg,
34                            std::vector<SetSpeedEvent>&& sse)
35 {
36     return [pg = std::move(pg),
37             sse = std::move(sse)](auto& zone, auto& group)
38     {
39         // Compare given precondition entries
40         auto precondState = std::all_of(
41             pg.begin(),
42             pg.end(),
43             [&zone](auto const& entry)
44             {
45                 try
46                 {
47                     return zone.getPropValueVariant(
48                         std::get<pcPathPos>(entry),
49                         std::get<pcIntfPos>(entry),
50                         std::get<pcPropPos>(entry)) ==
51                                 std::get<pcValuePos>(entry);
52                 }
53                 catch (const std::out_of_range& oore)
54                 {
55                     // Default to property variants not equal when not found
56                     return false;
57                 }
58             });
59 
60         if (precondState)
61         {
62             log<level::DEBUG>(
63                 "Preconditions passed, init the associated events",
64                 entry("EVENT_COUNT=%u", sse.size()));
65             // Init the events when all the precondition(s) are true
66             std::for_each(
67                 sse.begin(),
68                 sse.end(),
69                 [&zone](auto const& entry)
70                 {
71                     zone.initEvent(entry);
72                 });
73         }
74         else
75         {
76             log<level::DEBUG>(
77                 "Preconditions not met for events, events removed if present",
78                 entry("EVENT_COUNT=%u", sse.size()));
79             // Unsubscribe the events' signals when any precondition is false
80             std::for_each(
81                 sse.begin(),
82                 sse.end(),
83                 [&zone](auto const& entry)
84                 {
85                     zone.removeEvent(entry);
86                 });
87             zone.setFullSpeed();
88         }
89         // Update group's fan control active allowed
90         zone.setActiveAllow(&group, precondState);
91     };
92 }
93 
94 } // namespace precondition
95 } // namespace control
96 } // namespace fan
97 } // namespace phosphor
98