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