blob: 029a69a51b52a8143964585d25906ed01453970b [file] [log] [blame]
Matthew Barthb280bfa2017-09-15 09:56:50 -05001#include "actions.hpp"
2
3namespace phosphor
4{
5namespace fan
6{
7namespace control
8{
9namespace action
10{
11
12using namespace phosphor::fan;
13
William A. Kennington III122b8432018-10-30 18:39:21 -070014Action call_actions_based_on_timer(TimerConf&& tConf,
15 std::vector<Action>&& actions)
Matthew Barth2a646c52017-10-05 17:04:11 -050016{
17 return [tConf = std::move(tConf),
18 actions = std::move(actions)](control::Zone& zone,
19 const Group& group)
20 {
21 try
22 {
23 // Find any services that do not have an owner
24 auto services = zone.getGroupServices(&group);
25 auto setTimer = std::any_of(
26 services.begin(),
27 services.end(),
28 [](const auto& s)
29 {
30 return !std::get<hasOwnerPos>(s);
31 });
Matthew Barthd7b716a2018-11-16 13:37:57 -060032 auto it = zone.getTimerEvents().find(__func__);
33 if (it != zone.getTimerEvents().end())
Matthew Barth2a646c52017-10-05 17:04:11 -050034 {
Matthew Barthd7b716a2018-11-16 13:37:57 -060035 auto& timers = it->second;
36 auto timerIter = zone.findTimer(group, actions, timers);
37 if (setTimer && timerIter == timers.end())
Matthew Barth2a646c52017-10-05 17:04:11 -050038 {
Matthew Barthd7b716a2018-11-16 13:37:57 -060039 // No timer exists yet for action, add timer
40 zone.addTimer(__func__, group, actions, tConf);
Matthew Barth2a646c52017-10-05 17:04:11 -050041 }
Matthew Barthd7b716a2018-11-16 13:37:57 -060042 else if (!setTimer && timerIter != timers.end())
43 {
44 // Remove any timer for this group
45 timers.erase(timerIter);
46 if (timers.empty())
47 {
48 zone.getTimerEvents().erase(it);
49 }
50 }
51 }
52 else if (setTimer)
53 {
54 // No timer exists yet for event, add timer
55 zone.addTimer(__func__, group, actions, tConf);
Matthew Barth2a646c52017-10-05 17:04:11 -050056 }
57 }
58 catch (const std::out_of_range& oore)
59 {
60 // Group not found, no timers set
61 }
62 };
63}
64
Matthew Barth98726c42017-10-17 10:35:20 -050065void default_floor_on_missing_owner(Zone& zone, const Group& group)
66{
Matthew Barth480787c2017-11-06 11:00:00 -060067 // Set/update the services of the group
68 zone.setServices(&group);
Matthew Barth98726c42017-10-17 10:35:20 -050069 auto services = zone.getGroupServices(&group);
70 auto defFloor = std::any_of(
71 services.begin(),
72 services.end(),
73 [](const auto& s)
74 {
75 return !std::get<hasOwnerPos>(s);
76 });
77 if (defFloor)
78 {
79 zone.setFloor(zone.getDefFloor());
80 }
81 // Update fan control floor change allowed
82 zone.setFloorChangeAllow(&group, !defFloor);
83}
84
Matthew Barth0decd1b2017-10-24 15:58:17 -050085Action set_speed_on_missing_owner(uint64_t speed)
86{
87 return [speed](control::Zone& zone, const Group& group)
88 {
Matthew Barth480787c2017-11-06 11:00:00 -060089 // Set/update the services of the group
90 zone.setServices(&group);
Matthew Barth0decd1b2017-10-24 15:58:17 -050091 auto services = zone.getGroupServices(&group);
92 auto missingOwner = std::any_of(
93 services.begin(),
94 services.end(),
95 [](const auto& s)
96 {
97 return !std::get<hasOwnerPos>(s);
98 });
99 if (missingOwner)
100 {
101 zone.setSpeed(speed);
102 }
103 // Update group's fan control active allowed based on action results
104 zone.setActiveAllow(&group, !missingOwner);
105 };
106}
107
Matthew Barthb280bfa2017-09-15 09:56:50 -0500108void set_request_speed_base_with_max(control::Zone& zone,
109 const Group& group)
110{
111 int64_t base = 0;
112 std::for_each(
113 group.begin(),
114 group.end(),
115 [&zone, &base](auto const& entry)
116 {
117 try
118 {
119 auto value = zone.template getPropertyValue<int64_t>(
Matthew Barth146b7392018-03-08 16:17:58 -0600120 std::get<pathPos>(entry),
121 std::get<intfPos>(entry),
122 std::get<propPos>(entry));
Matthew Barthb280bfa2017-09-15 09:56:50 -0500123 base = std::max(base, value);
124 }
125 catch (const std::out_of_range& oore)
126 {
127 // Property value not found, base request speed unchanged
128 }
129 });
130 // A request speed base of 0 defaults to the current target speed
131 zone.setRequestSpeedBase(base);
132}
133
134Action set_floor_from_average_sensor_value(
135 std::map<int64_t, uint64_t>&& val_to_speed)
136{
137 return [val_to_speed = std::move(val_to_speed)](control::Zone& zone,
138 const Group& group)
139 {
140 auto speed = zone.getDefFloor();
141 if (group.size() != 0)
142 {
143 auto count = 0;
144 auto sumValue = std::accumulate(
145 group.begin(),
146 group.end(),
147 0,
148 [&zone, &count](int64_t sum, auto const& entry)
149 {
150 try
151 {
152 return sum +
153 zone.template getPropertyValue<int64_t>(
Matthew Barth146b7392018-03-08 16:17:58 -0600154 std::get<pathPos>(entry),
155 std::get<intfPos>(entry),
156 std::get<propPos>(entry));
Matthew Barthb280bfa2017-09-15 09:56:50 -0500157 }
158 catch (const std::out_of_range& oore)
159 {
160 count++;
161 return sum;
162 }
163 });
164 if ((group.size() - count) > 0)
165 {
166 auto groupSize = static_cast<int64_t>(group.size());
167 auto avgValue = sumValue / (groupSize - count);
168 auto it = std::find_if(
169 val_to_speed.begin(),
170 val_to_speed.end(),
171 [&avgValue](auto const& entry)
172 {
173 return avgValue < entry.first;
174 }
175 );
176 if (it != std::end(val_to_speed))
177 {
178 speed = (*it).second;
179 }
180 }
181 }
182 zone.setFloor(speed);
183 };
184}
185
186Action set_ceiling_from_average_sensor_value(
187 std::map<int64_t, uint64_t>&& val_to_speed)
188{
189 return [val_to_speed = std::move(val_to_speed)](Zone& zone,
190 const Group& group)
191 {
192 auto speed = zone.getCeiling();
193 if (group.size() != 0)
194 {
195 auto count = 0;
196 auto sumValue = std::accumulate(
197 group.begin(),
198 group.end(),
199 0,
200 [&zone, &count](int64_t sum, auto const& entry)
201 {
202 try
203 {
204 return sum +
205 zone.template getPropertyValue<int64_t>(
Matthew Barth146b7392018-03-08 16:17:58 -0600206 std::get<pathPos>(entry),
207 std::get<intfPos>(entry),
208 std::get<propPos>(entry));
Matthew Barthb280bfa2017-09-15 09:56:50 -0500209 }
210 catch (const std::out_of_range& oore)
211 {
212 count++;
213 return sum;
214 }
215 });
216 if ((group.size() - count) > 0)
217 {
218 auto groupSize = static_cast<int64_t>(group.size());
219 auto avgValue = sumValue / (groupSize - count);
220 auto prevValue = zone.swapCeilingKeyValue(avgValue);
221 if (avgValue != prevValue)
222 {// Only check if previous and new values differ
223 if (avgValue < prevValue)
224 {// Value is decreasing from previous
225 for (auto it = val_to_speed.rbegin();
226 it != val_to_speed.rend();
227 ++it)
228 {
229 if (it == val_to_speed.rbegin() &&
230 avgValue >= it->first)
231 {
232 // Value is at/above last map key, set
233 // ceiling speed to the last map key's value
234 speed = it->second;
235 break;
236 }
237 else if (std::next(it, 1) == val_to_speed.rend() &&
238 avgValue <= it->first)
239 {
240 // Value is at/below first map key, set
241 // ceiling speed to the first map key's value
242 speed = it->second;
243 break;
244 }
245 if (avgValue < it->first &&
246 it->first <= prevValue)
247 {
248 // Value decreased & transitioned across
249 // a map key, update ceiling speed to this
250 // map key's value when new value is below
251 // map's key and the key is at/below the
252 // previous value
253 speed = it->second;
254 }
255 }
256 }
257 else
258 {// Value is increasing from previous
259 for (auto it = val_to_speed.begin();
260 it != val_to_speed.end();
261 ++it)
262 {
263 if (it == val_to_speed.begin() &&
264 avgValue <= it->first)
265 {
266 // Value is at/below first map key, set
267 // ceiling speed to the first map key's value
268 speed = it->second;
269 break;
270 }
271 else if (std::next(it, 1) == val_to_speed.end() &&
272 avgValue >= it->first)
273 {
274 // Value is at/above last map key, set
275 // ceiling speed to the last map key's value
276 speed = it->second;
277 break;
278 }
279 if (avgValue > it->first &&
280 it->first >= prevValue)
281 {
282 // Value increased & transitioned across
283 // a map key, update ceiling speed to this
284 // map key's value when new value is above
285 // map's key and the key is at/above the
286 // previous value
287 speed = it->second;
288 }
289 }
290 }
291 }
292 }
293 }
294 zone.setCeiling(speed);
295 };
296}
297
298} // namespace action
299} // namespace control
300} // namespace fan
301} // namespace phosphor