blob: 406af13359d375244d19d24bb73f43a9be405b19 [file] [log] [blame]
Matt Spinler7f88fe62017-04-10 14:39:02 -05001#pragma once
Matthew Bartha9561842017-06-29 11:43:45 -05002#include <chrono>
Matt Spinler7f88fe62017-04-10 14:39:02 -05003#include <vector>
Matthew Barthbfb1a562017-10-05 17:03:40 -05004#include <cassert>
Matthew Barthe0ca13e2017-06-13 16:29:09 -05005#include <algorithm>
Matt Spinler7f88fe62017-04-10 14:39:02 -05006#include <sdbusplus/bus.hpp>
7#include "fan.hpp"
8#include "types.hpp"
Matthew Barth8600d9a2017-06-23 14:38:05 -05009#include "timer.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -050010
11namespace phosphor
12{
13namespace fan
14{
15namespace control
16{
17
18/**
Matthew Barth14184132017-05-19 14:37:30 -050019 * The mode fan control will run in:
20 * - init - only do the initialization steps
21 * - control - run normal control algorithms
22 */
23enum class Mode
24{
25 init,
26 control
27};
28
29/**
Matt Spinler7f88fe62017-04-10 14:39:02 -050030 * @class Represents a fan control zone, which is a group of fans
31 * that behave the same.
32 */
33class Zone
34{
35 public:
36
37 Zone() = delete;
38 Zone(const Zone&) = delete;
Matthew Barth0081fdb2017-11-14 14:02:34 -060039 Zone(Zone&&) = delete;
Matt Spinler7f88fe62017-04-10 14:39:02 -050040 Zone& operator=(const Zone&) = delete;
41 Zone& operator=(Zone&&) = delete;
42 ~Zone() = default;
43
44 /**
45 * Constructor
46 * Creates the appropriate fan objects based on
47 * the zone definition data passed in.
48 *
Matthew Barth14184132017-05-19 14:37:30 -050049 * @param[in] mode - mode of fan control
Matt Spinler7f88fe62017-04-10 14:39:02 -050050 * @param[in] bus - the dbus object
Matthew Barth8600d9a2017-06-23 14:38:05 -050051 * @param[in] events - sd_event pointer
Matt Spinler7f88fe62017-04-10 14:39:02 -050052 * @param[in] def - the fan zone definition data
53 */
Matthew Barth14184132017-05-19 14:37:30 -050054 Zone(Mode mode,
55 sdbusplus::bus::bus& bus,
Matthew Barth8600d9a2017-06-23 14:38:05 -050056 phosphor::fan::event::EventPtr& events,
Matt Spinler7f88fe62017-04-10 14:39:02 -050057 const ZoneDefinition& def);
58
59 /**
60 * Sets all fans in the zone to the speed
Matthew Barth60b00762017-08-15 13:39:06 -050061 * passed in when the zone is active
Matt Spinler7f88fe62017-04-10 14:39:02 -050062 *
63 * @param[in] speed - the fan speed
64 */
65 void setSpeed(uint64_t speed);
66
67 /**
Matthew Barth60b00762017-08-15 13:39:06 -050068 * Sets the zone to full speed regardless of zone's active state
Matt Spinler7f88fe62017-04-10 14:39:02 -050069 */
Matthew Barth60b00762017-08-15 13:39:06 -050070 void setFullSpeed();
Matt Spinler7f88fe62017-04-10 14:39:02 -050071
Matthew Barth38a93a82017-05-11 14:12:27 -050072 /**
Matthew Barth861d77c2017-05-22 14:18:25 -050073 * @brief Sets the automatic fan control allowed active state
74 *
75 * @param[in] group - A group that affects the active state
76 * @param[in] isActiveAllow - Active state according to group
77 */
78 void setActiveAllow(const Group* group, bool isActiveAllow);
79
80 /**
Matthew Barth98726c42017-10-17 10:35:20 -050081 * @brief Sets the floor change allowed state
82 *
83 * @param[in] group - A group that affects floor changes
84 * @param[in] isAllow - Allow state according to group
85 */
86 inline void setFloorChangeAllow(const Group* group, bool isAllow)
87 {
88 _floorChange[*(group)] = isAllow;
89 }
90
91 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -060092 * @brief Sets the decrease allowed state of a group
93 *
94 * @param[in] group - A group that affects speed decreases
95 * @param[in] isAllow - Allow state according to group
96 */
97 inline void setDecreaseAllow(const Group* group, bool isAllow)
98 {
99 _decAllowed[*(group)] = isAllow;
100 }
101
102 /**
Matthew Barth38a93a82017-05-11 14:12:27 -0500103 * @brief Sets a given object's property value
104 *
105 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500106 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -0500107 * @param[in] property - Property name
108 * @param[in] value - Property value
109 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500110 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -0500111 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500112 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -0500113 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500114 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -0500115 {
Matthew Barthcec5ab72017-06-02 15:20:56 -0500116 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -0500117 };
118
Matthew Barth17d1fe22017-05-11 15:00:36 -0500119 /**
120 * @brief Get the value of an object's property
121 *
122 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500123 * @param[in] interface - Interface name containing the property
Matthew Barth17d1fe22017-05-11 15:00:36 -0500124 * @param[in] property - Property name
125 *
126 * @return - The property value
127 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500128 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500129 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500130 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500131 const std::string& property)
132 {
Matthew Barth9e741ed2017-06-02 16:29:09 -0500133 return sdbusplus::message::variant_ns::get<T>(
Matthew Barthbc651602017-08-10 16:59:43 -0500134 _properties.at(object).at(interface).at(property));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500135 };
136
Matthew Barth1de66622017-06-12 13:13:02 -0500137 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500138 * @brief Get the object's property variant
139 *
140 * @param[in] object - Name of the object containing the property
141 * @param[in] interface - Interface name containing the property
142 * @param[in] property - Property name
143 *
144 * @return - The property variant
145 */
146 inline auto getPropValueVariant(const std::string& object,
147 const std::string& interface,
148 const std::string& property)
149 {
150 return _properties.at(object).at(interface).at(property);
151 };
152
153 /**
Matthew Barth55dea642017-11-06 13:34:32 -0600154 * @brief Remove a service associated to a group
155 *
156 * @param[in] group - Group associated with service
157 * @param[in] name - Service name to remove
158 */
159 void removeService(const Group* group,
160 const std::string& name);
161
162 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500163 * @brief Set or update a service name owner in use
164 *
165 * @param[in] group - Group associated with service
166 * @param[in] name - Service name
167 * @param[in] hasOwner - Whether the service is owned or not
168 */
169 void setServiceOwner(const Group* group,
170 const std::string& name,
171 const bool hasOwner);
172
173 /**
Matthew Barth480787c2017-11-06 11:00:00 -0600174 * @brief Set or update all services for a group
175 *
176 * @param[in] group - Group to get service names for
177 */
178 void setServices(const Group* group);
179
180 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500181 * @brief Get the group's list of service names
182 *
183 * @param[in] group - Group to get service names for
184 *
185 * @return - The list of service names
186 */
187 inline auto getGroupServices(const Group* group)
188 {
189 return _services.at(*group);
190 }
191
192 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500193 * @brief Initialize a set speed event properties and actions
194 *
195 * @param[in] event - Set speed event
196 */
197 void initEvent(const SetSpeedEvent& event);
198
199 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500200 * @brief Removes all the set speed event properties and actions
201 *
202 * @param[in] event - Set speed event
203 */
204 void removeEvent(const SetSpeedEvent& event);
205
206 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500207 * @brief Get the default floor speed
208 *
209 * @return - The defined default floor speed
210 */
211 inline auto getDefFloor()
212 {
213 return _defFloorSpeed;
214 };
215
Matthew Barth4af419c2017-06-12 13:39:31 -0500216 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500217 * @brief Get the ceiling speed
218 *
219 * @return - The current ceiling speed
220 */
221 inline auto& getCeiling() const
222 {
223 return _ceilingSpeed;
224 };
225
226 /**
227 * @brief Set the ceiling speed to the given speed
228 *
229 * @param[in] speed - Speed to set the ceiling to
230 */
231 inline void setCeiling(uint64_t speed)
232 {
233 _ceilingSpeed = speed;
234 };
235
236 /**
237 * @brief Swaps the ceiling key value with what's given and
238 * returns the value that was swapped.
239 *
240 * @param[in] keyValue - New ceiling key value
241 *
242 * @return - Ceiling key value prior to swapping
243 */
244 inline auto swapCeilingKeyValue(int64_t keyValue)
245 {
246 std::swap(_ceilingKeyValue, keyValue);
247 return keyValue;
248 };
249
Matthew Barth24623522017-06-21 14:09:57 -0500250 /**
251 * @brief Get the increase speed delta
252 *
253 * @return - The current increase speed delta
254 */
255 inline auto& getIncSpeedDelta() const
256 {
257 return _incSpeedDelta;
258 };
259
Matthew Barth240397b2017-06-22 11:23:30 -0500260 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500261 * @brief Get the decrease speed delta
262 *
263 * @return - The current decrease speed delta
264 */
265 inline auto& getDecSpeedDelta() const
266 {
267 return _decSpeedDelta;
268 };
269
270 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500271 * @brief Set the floor speed to the given speed and increase target
Matthew Barth98726c42017-10-17 10:35:20 -0500272 * speed to the floor when target is below floor where floor changes
273 * are allowed.
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500274 *
275 * @param[in] speed - Speed to set the floor to
276 */
277 void setFloor(uint64_t speed);
278
279 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500280 * @brief Set the requested speed base to be used as the speed to
281 * base a new requested speed target from
282 *
283 * @param[in] speedBase - Base speed value to use
284 */
285 inline void setRequestSpeedBase(uint64_t speedBase)
286 {
287 _requestSpeedBase = speedBase;
288 };
289
290 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500291 * @brief Calculate the requested target speed from the given delta
292 * and increase the fan speeds, not going above the ceiling.
293 *
294 * @param[in] targetDelta - The delta to increase the target speed by
295 */
296 void requestSpeedIncrease(uint64_t targetDelta);
297
Matthew Barth0ce99d82017-06-22 15:07:29 -0500298 /**
299 * @brief Calculate the requested target speed from the given delta
300 * and increase the fan speeds, not going above the ceiling.
301 *
302 * @param[in] targetDelta - The delta to increase the target speed by
303 */
304 void requestSpeedDecrease(uint64_t targetDelta);
305
Matthew Barth8600d9a2017-06-23 14:38:05 -0500306 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500307 * @brief Callback function for the increase timer that delays
308 * processing of requested speed increases while fans are increasing
309 */
310 void incTimerExpired();
311
312 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500313 * @brief Callback function for the decrease timer that processes any
314 * requested speed decreases if allowed
315 */
316 void decTimerExpired();
317
Matthew Barth90149802017-08-15 10:51:37 -0500318 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500319 * @brief Get the event pointer used with this zone's timers
320 *
321 * @return - The Dbus event pointer for timers
322 */
323 inline auto& getEventPtr()
324 {
325 return _sdEvents;
326 }
327
328 /**
329 * @brief Get the list of timer events
330 *
331 * @return - List of timer events
332 */
333 inline auto& getTimerEvents()
334 {
335 return _timerEvents;
336 }
337
338 /**
339 * @brief Find the first instance of a timer event
340 *
341 * @param[in] eventGroup - Group associated with a timer
342 * @param[in] eventActions - List of actions associated with a timer
343 *
344 * @return - Iterator to the timer event
345 */
346 std::vector<TimerEvent>::iterator findTimer(
347 const Group& eventGroup,
348 const std::vector<Action>& eventActions);
349
350 /**
351 * @brief Add a timer to the list of timer based events
352 *
353 * @param[in] data - Event data for timer
354 * @param[in] timer - Timer to be added
355 */
356 inline void addTimer(
357 std::unique_ptr<EventData>&& data,
358 std::unique_ptr<phosphor::fan::util::Timer>&& timer)
359 {
360 _timerEvents.emplace_back(std::move(data), std::move(timer));
361 };
362
363 /**
364 * @brief Remove the given timer event
365 *
366 * @param[in] teIter - Iterator pointing to the timer event to remove
367 */
368 inline void removeTimer(std::vector<TimerEvent>::iterator& teIter)
369 {
370 assert(teIter != std::end(_timerEvents));
371 std::get<timerEventDataPos>(*teIter).reset();
372 std::get<timerTimerPos>(*teIter).reset();
373 _timerEvents.erase(teIter);
374 }
375
376 /**
Matthew Barth90149802017-08-15 10:51:37 -0500377 * @brief Callback function for event timers that processes the given
Matthew Barthf9201ab2017-09-11 16:07:58 -0500378 * actions for a group
Matthew Barth90149802017-08-15 10:51:37 -0500379 *
Matthew Barthf9201ab2017-09-11 16:07:58 -0500380 * @param[in] eventGroup - Group to process actions on
381 * @param[in] eventActions - List of event actions to run
Matthew Barth90149802017-08-15 10:51:37 -0500382 */
Matthew Barthf9201ab2017-09-11 16:07:58 -0500383 void timerExpired(Group eventGroup, std::vector<Action> eventActions);
Matthew Barth90149802017-08-15 10:51:37 -0500384
Matt Spinler7f88fe62017-04-10 14:39:02 -0500385 private:
386
387 /**
388 * The dbus object
389 */
390 sdbusplus::bus::bus& _bus;
391
392 /**
393 * Full speed for the zone
394 */
395 const uint64_t _fullSpeed;
396
397 /**
398 * The zone number
399 */
400 const size_t _zoneNum;
401
402 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500403 * The default floor speed for the zone
404 */
405 const uint64_t _defFloorSpeed;
406
407 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500408 * The default ceiling speed for the zone
409 */
410 const uint64_t _defCeilingSpeed;
411
412 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500413 * The floor speed to not go below
414 */
415 uint64_t _floorSpeed = _defFloorSpeed;
416
417 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500418 * The ceiling speed to not go above
419 */
420 uint64_t _ceilingSpeed = _defCeilingSpeed;
421
422 /**
423 * The previous sensor value for calculating the ceiling
424 */
425 int64_t _ceilingKeyValue = 0;
426
427 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500428 * Automatic fan control active state
429 */
430 bool _isActive = true;
431
432 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500433 * Target speed for this zone
434 */
435 uint64_t _targetSpeed = _fullSpeed;
436
437 /**
Matthew Barth24623522017-06-21 14:09:57 -0500438 * Speed increase delta
439 */
440 uint64_t _incSpeedDelta = 0;
441
442 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500443 * Speed decrease delta
444 */
445 uint64_t _decSpeedDelta = 0;
446
447 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500448 * Requested speed base
449 */
450 uint64_t _requestSpeedBase = 0;
451
452 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500453 * Speed increase delay in seconds
454 */
455 std::chrono::seconds _incDelay;
456
457 /**
458 * Speed decrease interval in seconds
459 */
460 std::chrono::seconds _decInterval;
461
462 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500463 * The increase timer object
464 */
465 phosphor::fan::util::Timer _incTimer;
466
467 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500468 * The decrease timer object
469 */
470 phosphor::fan::util::Timer _decTimer;
471
472 /**
Matthew Barth90149802017-08-15 10:51:37 -0500473 * Dbus event used on set speed event timers
474 */
475 phosphor::fan::event::EventPtr& _sdEvents;
476
477 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500478 * The vector of fans in this zone
479 */
480 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500481
482 /**
483 * @brief Map of object property values
484 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500485 std::map<std::string,
486 std::map<std::string,
487 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500488 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500489
490 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500491 * @brief Map of active fan control allowed by groups
492 */
Matthew Barth60b00762017-08-15 13:39:06 -0500493 std::map<const Group, bool> _active;
Matthew Barth861d77c2017-05-22 14:18:25 -0500494
495 /**
Matthew Barth98726c42017-10-17 10:35:20 -0500496 * @brief Map of floor change allowed by groups
497 */
498 std::map<const Group, bool> _floorChange;
499
500 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -0600501 * @brief Map of groups controlling decreases allowed
502 */
503 std::map<const Group, bool> _decAllowed;
504
505 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500506 * @brief Map of group service names
507 */
508 std::map<const Group, std::vector<Service>> _services;
509
510 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500511 * @brief List of signal event arguments and Dbus matches for callbacks
Matthew Barth38a93a82017-05-11 14:12:27 -0500512 */
Matthew Barthf6b76d82017-08-04 12:58:02 -0500513 std::vector<SignalEvent> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500514
515 /**
Matthew Barth90149802017-08-15 10:51:37 -0500516 * @brief List of timers for events
517 */
Matthew Barthbfb1a562017-10-05 17:03:40 -0500518 std::vector<TimerEvent> _timerEvents;
Matthew Barth90149802017-08-15 10:51:37 -0500519
520 /**
Matthew Barth4e728542017-09-14 16:47:55 -0500521 * @brief Get the request speed base if defined, otherwise the
522 * the current target speed is returned
523 *
524 * @return - The request speed base or current target speed
525 */
526 inline auto getRequestSpeedBase() const
527 {
528 return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
529 };
530
531 /**
Matthew Barth34f1bda2017-05-31 13:45:36 -0500532 * @brief Dbus signal change callback handler
Matthew Barth38a93a82017-05-11 14:12:27 -0500533 *
Matthew Barth34f1bda2017-05-31 13:45:36 -0500534 * @param[in] msg - Expanded sdbusplus message data
535 * @param[in] eventData - The single event's data
Matthew Barth38a93a82017-05-11 14:12:27 -0500536 */
Matthew Barth34f1bda2017-05-31 13:45:36 -0500537 void handleEvent(sdbusplus::message::message& msg,
538 const EventData* eventData);
Matt Spinler7f88fe62017-04-10 14:39:02 -0500539};
540
541}
542}
543}