blob: a6082932eeaa5fc87ccdf698cbb33e032993e98d [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
14void 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
40Action 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
92Action 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