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