1 #include "actions.hpp"
2 
3 namespace phosphor
4 {
5 namespace fan
6 {
7 namespace control
8 {
9 namespace action
10 {
11 
12 using namespace phosphor::fan;
13 
14 void set_request_speed_base_with_max(control::Zone& zone,
15                                      const Group& group)
16 {
17     int64_t base = 0;
18     std::for_each(
19             group.begin(),
20             group.end(),
21             [&zone, &base](auto const& entry)
22         {
23             try
24             {
25                 auto value = zone.template getPropertyValue<int64_t>(
26                         entry.first,
27                         std::get<intfPos>(entry.second),
28                         std::get<propPos>(entry.second));
29                 base = std::max(base, value);
30             }
31             catch (const std::out_of_range& oore)
32             {
33                 // Property value not found, base request speed unchanged
34             }
35         });
36     // A request speed base of 0 defaults to the current target speed
37     zone.setRequestSpeedBase(base);
38 }
39 
40 Action set_floor_from_average_sensor_value(
41         std::map<int64_t, uint64_t>&& val_to_speed)
42 {
43     return [val_to_speed = std::move(val_to_speed)](control::Zone& zone,
44                                                     const Group& group)
45     {
46         auto speed = zone.getDefFloor();
47         if (group.size() != 0)
48         {
49             auto count = 0;
50             auto sumValue = std::accumulate(
51                     group.begin(),
52                     group.end(),
53                     0,
54                     [&zone, &count](int64_t sum, auto const& entry)
55                     {
56                         try
57                         {
58                             return sum +
59                                 zone.template getPropertyValue<int64_t>(
60                                     entry.first,
61                                     std::get<intfPos>(entry.second),
62                                     std::get<propPos>(entry.second));
63                         }
64                         catch (const std::out_of_range& oore)
65                         {
66                             count++;
67                             return sum;
68                         }
69                     });
70             if ((group.size() - count) > 0)
71             {
72                 auto groupSize = static_cast<int64_t>(group.size());
73                 auto avgValue = sumValue / (groupSize - count);
74                 auto it = std::find_if(
75                     val_to_speed.begin(),
76                     val_to_speed.end(),
77                     [&avgValue](auto const& entry)
78                     {
79                         return avgValue < entry.first;
80                     }
81                 );
82                 if (it != std::end(val_to_speed))
83                 {
84                     speed = (*it).second;
85                 }
86             }
87         }
88         zone.setFloor(speed);
89     };
90 }
91 
92 Action set_ceiling_from_average_sensor_value(
93         std::map<int64_t, uint64_t>&& val_to_speed)
94 {
95     return [val_to_speed = std::move(val_to_speed)](Zone& zone,
96                                                     const Group& group)
97     {
98         auto speed = zone.getCeiling();
99         if (group.size() != 0)
100         {
101             auto count = 0;
102             auto sumValue = std::accumulate(
103                     group.begin(),
104                     group.end(),
105                     0,
106                     [&zone, &count](int64_t sum, auto const& entry)
107                     {
108                         try
109                         {
110                             return sum +
111                                 zone.template getPropertyValue<int64_t>(
112                                     entry.first,
113                                     std::get<intfPos>(entry.second),
114                                     std::get<propPos>(entry.second));
115                         }
116                         catch (const std::out_of_range& oore)
117                         {
118                             count++;
119                             return sum;
120                         }
121                     });
122             if ((group.size() - count) > 0)
123             {
124                 auto groupSize = static_cast<int64_t>(group.size());
125                 auto avgValue = sumValue / (groupSize - count);
126                 auto prevValue = zone.swapCeilingKeyValue(avgValue);
127                 if (avgValue != prevValue)
128                 {// Only check if previous and new values differ
129                     if (avgValue < prevValue)
130                     {// Value is decreasing from previous
131                         for (auto it = val_to_speed.rbegin();
132                              it != val_to_speed.rend();
133                              ++it)
134                         {
135                             if (it == val_to_speed.rbegin() &&
136                                 avgValue >= it->first)
137                             {
138                                 // Value is at/above last map key, set
139                                 // ceiling speed to the last map key's value
140                                 speed = it->second;
141                                 break;
142                             }
143                             else if (std::next(it, 1) == val_to_speed.rend() &&
144                                      avgValue <= it->first)
145                             {
146                                 // Value is at/below first map key, set
147                                 // ceiling speed to the first map key's value
148                                 speed = it->second;
149                                 break;
150                             }
151                             if (avgValue < it->first &&
152                                 it->first <= prevValue)
153                             {
154                                 // Value decreased & transitioned across
155                                 // a map key, update ceiling speed to this
156                                 // map key's value when new value is below
157                                 // map's key and the key is at/below the
158                                 // previous value
159                                 speed = it->second;
160                             }
161                         }
162                     }
163                     else
164                     {// Value is increasing from previous
165                         for (auto it = val_to_speed.begin();
166                              it != val_to_speed.end();
167                              ++it)
168                         {
169                             if (it == val_to_speed.begin() &&
170                                 avgValue <= it->first)
171                             {
172                                 // Value is at/below first map key, set
173                                 // ceiling speed to the first map key's value
174                                 speed = it->second;
175                                 break;
176                             }
177                             else if (std::next(it, 1) == val_to_speed.end() &&
178                                      avgValue >= it->first)
179                             {
180                                 // Value is at/above last map key, set
181                                 // ceiling speed to the last map key's value
182                                 speed = it->second;
183                                 break;
184                             }
185                             if (avgValue > it->first &&
186                                 it->first >= prevValue)
187                             {
188                                 // Value increased & transitioned across
189                                 // a map key, update ceiling speed to this
190                                 // map key's value when new value is above
191                                 // map's key and the key is at/above the
192                                 // previous value
193                                 speed = it->second;
194                             }
195                         }
196                     }
197                 }
198             }
199         }
200         zone.setCeiling(speed);
201     };
202 }
203 
204 } // namespace action
205 } // namespace control
206 } // namespace fan
207 } // namespace phosphor
208