blob: e035a643b75f0d92cf7320487631e0fdb4bf74a4 [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>
William A. Kennington III1cfc2f12018-10-19 17:29:46 -07007#include <sdeventplus/event.hpp>
Matt Spinler7f88fe62017-04-10 14:39:02 -05008#include "fan.hpp"
9#include "types.hpp"
Matthew Barth8600d9a2017-06-23 14:38:05 -050010#include "timer.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -050011
12namespace phosphor
13{
14namespace fan
15{
16namespace control
17{
18
19/**
Matthew Barth14184132017-05-19 14:37:30 -050020 * The mode fan control will run in:
21 * - init - only do the initialization steps
22 * - control - run normal control algorithms
23 */
24enum class Mode
25{
26 init,
27 control
28};
29
30/**
Matt Spinler7f88fe62017-04-10 14:39:02 -050031 * @class Represents a fan control zone, which is a group of fans
32 * that behave the same.
33 */
34class Zone
35{
36 public:
37
38 Zone() = delete;
39 Zone(const Zone&) = delete;
Matthew Barth0081fdb2017-11-14 14:02:34 -060040 Zone(Zone&&) = delete;
Matt Spinler7f88fe62017-04-10 14:39:02 -050041 Zone& operator=(const Zone&) = delete;
42 Zone& operator=(Zone&&) = delete;
43 ~Zone() = default;
44
45 /**
46 * Constructor
47 * Creates the appropriate fan objects based on
48 * the zone definition data passed in.
49 *
Matthew Barth14184132017-05-19 14:37:30 -050050 * @param[in] mode - mode of fan control
Matt Spinler7f88fe62017-04-10 14:39:02 -050051 * @param[in] bus - the dbus object
William A. Kennington III1cfc2f12018-10-19 17:29:46 -070052 * @param[in] event - Event loop reference
Matt Spinler7f88fe62017-04-10 14:39:02 -050053 * @param[in] def - the fan zone definition data
54 */
Matthew Barth14184132017-05-19 14:37:30 -050055 Zone(Mode mode,
56 sdbusplus::bus::bus& bus,
William A. Kennington III1cfc2f12018-10-19 17:29:46 -070057 const sdeventplus::Event& event,
Matt Spinler7f88fe62017-04-10 14:39:02 -050058 const ZoneDefinition& def);
59
60 /**
61 * Sets all fans in the zone to the speed
Matthew Barth60b00762017-08-15 13:39:06 -050062 * passed in when the zone is active
Matt Spinler7f88fe62017-04-10 14:39:02 -050063 *
64 * @param[in] speed - the fan speed
65 */
66 void setSpeed(uint64_t speed);
67
68 /**
Matthew Barth60b00762017-08-15 13:39:06 -050069 * Sets the zone to full speed regardless of zone's active state
Matt Spinler7f88fe62017-04-10 14:39:02 -050070 */
Matthew Barth60b00762017-08-15 13:39:06 -050071 void setFullSpeed();
Matt Spinler7f88fe62017-04-10 14:39:02 -050072
Matthew Barth38a93a82017-05-11 14:12:27 -050073 /**
Matthew Barth861d77c2017-05-22 14:18:25 -050074 * @brief Sets the automatic fan control allowed active state
75 *
76 * @param[in] group - A group that affects the active state
77 * @param[in] isActiveAllow - Active state according to group
78 */
79 void setActiveAllow(const Group* group, bool isActiveAllow);
80
81 /**
Matthew Barth98726c42017-10-17 10:35:20 -050082 * @brief Sets the floor change allowed state
83 *
84 * @param[in] group - A group that affects floor changes
85 * @param[in] isAllow - Allow state according to group
86 */
87 inline void setFloorChangeAllow(const Group* group, bool isAllow)
88 {
89 _floorChange[*(group)] = isAllow;
90 }
91
92 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -060093 * @brief Sets the decrease allowed state of a group
94 *
95 * @param[in] group - A group that affects speed decreases
96 * @param[in] isAllow - Allow state according to group
97 */
98 inline void setDecreaseAllow(const Group* group, bool isAllow)
99 {
100 _decAllowed[*(group)] = isAllow;
101 }
102
103 /**
Matthew Barth38a93a82017-05-11 14:12:27 -0500104 * @brief Sets a given object's property value
105 *
106 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500107 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -0500108 * @param[in] property - Property name
109 * @param[in] value - Property value
110 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500111 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -0500112 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500113 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -0500114 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500115 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -0500116 {
Matthew Barthcec5ab72017-06-02 15:20:56 -0500117 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -0500118 };
119
Matthew Barth17d1fe22017-05-11 15:00:36 -0500120 /**
121 * @brief Get the value of an object's property
122 *
123 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500124 * @param[in] interface - Interface name containing the property
Matthew Barth17d1fe22017-05-11 15:00:36 -0500125 * @param[in] property - Property name
126 *
127 * @return - The property value
128 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500129 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500130 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500131 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500132 const std::string& property)
133 {
Matthew Barth9e741ed2017-06-02 16:29:09 -0500134 return sdbusplus::message::variant_ns::get<T>(
Matthew Barthbc651602017-08-10 16:59:43 -0500135 _properties.at(object).at(interface).at(property));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500136 };
137
Matthew Barth1de66622017-06-12 13:13:02 -0500138 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500139 * @brief Get the object's property variant
140 *
141 * @param[in] object - Name of the object containing the property
142 * @param[in] interface - Interface name containing the property
143 * @param[in] property - Property name
144 *
145 * @return - The property variant
146 */
147 inline auto getPropValueVariant(const std::string& object,
148 const std::string& interface,
149 const std::string& property)
150 {
151 return _properties.at(object).at(interface).at(property);
152 };
153
154 /**
Matthew Barth1499a5c2018-03-20 15:52:33 -0500155 * @brief Remove an object's interface
156 *
157 * @param[in] object - Name of the object with the interface
158 * @param[in] interface - Interface name to remove
159 */
Matthew Barth30abbef2018-04-12 09:40:54 -0500160 inline void removeObjectInterface(const char* object,
161 const char* interface)
Matthew Barth1499a5c2018-03-20 15:52:33 -0500162 {
163 auto it = _properties.find(object);
164 if (it != std::end(_properties))
165 {
166 _properties[object].erase(interface);
167 }
168 }
169
170 /**
Matthew Barth55dea642017-11-06 13:34:32 -0600171 * @brief Remove a service associated to a group
172 *
173 * @param[in] group - Group associated with service
174 * @param[in] name - Service name to remove
175 */
176 void removeService(const Group* group,
177 const std::string& name);
178
179 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500180 * @brief Set or update a service name owner in use
181 *
182 * @param[in] group - Group associated with service
183 * @param[in] name - Service name
184 * @param[in] hasOwner - Whether the service is owned or not
185 */
186 void setServiceOwner(const Group* group,
187 const std::string& name,
188 const bool hasOwner);
189
190 /**
Matthew Barth480787c2017-11-06 11:00:00 -0600191 * @brief Set or update all services for a group
192 *
193 * @param[in] group - Group to get service names for
194 */
195 void setServices(const Group* group);
196
197 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500198 * @brief Get the group's list of service names
199 *
200 * @param[in] group - Group to get service names for
201 *
202 * @return - The list of service names
203 */
204 inline auto getGroupServices(const Group* group)
205 {
206 return _services.at(*group);
207 }
208
209 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500210 * @brief Initialize a set speed event properties and actions
211 *
212 * @param[in] event - Set speed event
213 */
214 void initEvent(const SetSpeedEvent& event);
215
216 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500217 * @brief Removes all the set speed event properties and actions
218 *
219 * @param[in] event - Set speed event
220 */
221 void removeEvent(const SetSpeedEvent& event);
222
223 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500224 * @brief Get the default floor speed
225 *
226 * @return - The defined default floor speed
227 */
228 inline auto getDefFloor()
229 {
230 return _defFloorSpeed;
231 };
232
Matthew Barth4af419c2017-06-12 13:39:31 -0500233 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500234 * @brief Get the ceiling speed
235 *
236 * @return - The current ceiling speed
237 */
238 inline auto& getCeiling() const
239 {
240 return _ceilingSpeed;
241 };
242
243 /**
244 * @brief Set the ceiling speed to the given speed
245 *
246 * @param[in] speed - Speed to set the ceiling to
247 */
248 inline void setCeiling(uint64_t speed)
249 {
250 _ceilingSpeed = speed;
251 };
252
253 /**
254 * @brief Swaps the ceiling key value with what's given and
255 * returns the value that was swapped.
256 *
257 * @param[in] keyValue - New ceiling key value
258 *
259 * @return - Ceiling key value prior to swapping
260 */
261 inline auto swapCeilingKeyValue(int64_t keyValue)
262 {
263 std::swap(_ceilingKeyValue, keyValue);
264 return keyValue;
265 };
266
Matthew Barth24623522017-06-21 14:09:57 -0500267 /**
268 * @brief Get the increase speed delta
269 *
270 * @return - The current increase speed delta
271 */
272 inline auto& getIncSpeedDelta() const
273 {
274 return _incSpeedDelta;
275 };
276
Matthew Barth240397b2017-06-22 11:23:30 -0500277 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500278 * @brief Get the decrease speed delta
279 *
280 * @return - The current decrease speed delta
281 */
282 inline auto& getDecSpeedDelta() const
283 {
284 return _decSpeedDelta;
285 };
286
287 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500288 * @brief Set the floor speed to the given speed and increase target
Matthew Barth98726c42017-10-17 10:35:20 -0500289 * speed to the floor when target is below floor where floor changes
290 * are allowed.
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500291 *
292 * @param[in] speed - Speed to set the floor to
293 */
294 void setFloor(uint64_t speed);
295
296 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500297 * @brief Set the requested speed base to be used as the speed to
298 * base a new requested speed target from
299 *
300 * @param[in] speedBase - Base speed value to use
301 */
302 inline void setRequestSpeedBase(uint64_t speedBase)
303 {
304 _requestSpeedBase = speedBase;
305 };
306
307 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500308 * @brief Calculate the requested target speed from the given delta
309 * and increase the fan speeds, not going above the ceiling.
310 *
311 * @param[in] targetDelta - The delta to increase the target speed by
312 */
313 void requestSpeedIncrease(uint64_t targetDelta);
314
Matthew Barth0ce99d82017-06-22 15:07:29 -0500315 /**
316 * @brief Calculate the requested target speed from the given delta
317 * and increase the fan speeds, not going above the ceiling.
318 *
319 * @param[in] targetDelta - The delta to increase the target speed by
320 */
321 void requestSpeedDecrease(uint64_t targetDelta);
322
Matthew Barth8600d9a2017-06-23 14:38:05 -0500323 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500324 * @brief Callback function for the increase timer that delays
325 * processing of requested speed increases while fans are increasing
326 */
327 void incTimerExpired();
328
329 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500330 * @brief Callback function for the decrease timer that processes any
331 * requested speed decreases if allowed
332 */
333 void decTimerExpired();
334
Matthew Barth90149802017-08-15 10:51:37 -0500335 /**
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700336 * @brief Get the event loop used with this zone's timers
Matthew Barthbfb1a562017-10-05 17:03:40 -0500337 *
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700338 * @return - The event loop for timers
Matthew Barthbfb1a562017-10-05 17:03:40 -0500339 */
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700340 inline auto& getEventLoop()
Matthew Barthbfb1a562017-10-05 17:03:40 -0500341 {
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700342 return _eventLoop;
Matthew Barthbfb1a562017-10-05 17:03:40 -0500343 }
344
345 /**
346 * @brief Get the list of timer events
347 *
348 * @return - List of timer events
349 */
350 inline auto& getTimerEvents()
351 {
352 return _timerEvents;
353 }
354
355 /**
356 * @brief Find the first instance of a timer event
357 *
358 * @param[in] eventGroup - Group associated with a timer
359 * @param[in] eventActions - List of actions associated with a timer
360 *
361 * @return - Iterator to the timer event
362 */
363 std::vector<TimerEvent>::iterator findTimer(
364 const Group& eventGroup,
365 const std::vector<Action>& eventActions);
366
367 /**
368 * @brief Add a timer to the list of timer based events
369 *
370 * @param[in] data - Event data for timer
371 * @param[in] timer - Timer to be added
372 */
373 inline void addTimer(
374 std::unique_ptr<EventData>&& data,
375 std::unique_ptr<phosphor::fan::util::Timer>&& timer)
376 {
377 _timerEvents.emplace_back(std::move(data), std::move(timer));
378 };
379
380 /**
381 * @brief Remove the given timer event
382 *
383 * @param[in] teIter - Iterator pointing to the timer event to remove
384 */
385 inline void removeTimer(std::vector<TimerEvent>::iterator& teIter)
386 {
387 assert(teIter != std::end(_timerEvents));
388 std::get<timerEventDataPos>(*teIter).reset();
389 std::get<timerTimerPos>(*teIter).reset();
390 _timerEvents.erase(teIter);
391 }
392
393 /**
Matthew Barth90149802017-08-15 10:51:37 -0500394 * @brief Callback function for event timers that processes the given
Matthew Barthf9201ab2017-09-11 16:07:58 -0500395 * actions for a group
Matthew Barth90149802017-08-15 10:51:37 -0500396 *
Matthew Barthf9201ab2017-09-11 16:07:58 -0500397 * @param[in] eventGroup - Group to process actions on
398 * @param[in] eventActions - List of event actions to run
Matthew Barth90149802017-08-15 10:51:37 -0500399 */
Matthew Barthf9201ab2017-09-11 16:07:58 -0500400 void timerExpired(Group eventGroup, std::vector<Action> eventActions);
Matthew Barth90149802017-08-15 10:51:37 -0500401
Matthew Bartha603ed02018-01-19 16:56:26 -0600402 /**
403 * @brief Get the service for a given path and interface from cached
404 * dataset and add a service that's not found
405 *
406 * @param[in] path - Path to get service for
407 * @param[in] intf - Interface to get service for
408 *
409 * @return - The service name
410 */
411 const std::string& getService(const std::string& path,
412 const std::string& intf);
413
414 /**
415 * @brief Add a set of services for a path and interface
416 * by retrieving all the path subtrees to the given depth
417 * from root for the interface
418 *
419 * @param[in] path - Path to add services for
420 * @param[in] intf - Interface to add services for
421 * @param[in] depth - Depth of tree traversal from root path
422 *
423 * @return - The associated service to the given path and interface
424 * or empty string for no service found
425 */
426 const std::string& addServices(const std::string& path,
427 const std::string& intf,
428 int32_t depth);
429
Matt Spinler7f88fe62017-04-10 14:39:02 -0500430 private:
431
432 /**
433 * The dbus object
434 */
435 sdbusplus::bus::bus& _bus;
436
437 /**
438 * Full speed for the zone
439 */
440 const uint64_t _fullSpeed;
441
442 /**
443 * The zone number
444 */
445 const size_t _zoneNum;
446
447 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500448 * The default floor speed for the zone
449 */
450 const uint64_t _defFloorSpeed;
451
452 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500453 * The default ceiling speed for the zone
454 */
455 const uint64_t _defCeilingSpeed;
456
457 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500458 * The floor speed to not go below
459 */
460 uint64_t _floorSpeed = _defFloorSpeed;
461
462 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500463 * The ceiling speed to not go above
464 */
465 uint64_t _ceilingSpeed = _defCeilingSpeed;
466
467 /**
468 * The previous sensor value for calculating the ceiling
469 */
470 int64_t _ceilingKeyValue = 0;
471
472 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500473 * Automatic fan control active state
474 */
475 bool _isActive = true;
476
477 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500478 * Target speed for this zone
479 */
480 uint64_t _targetSpeed = _fullSpeed;
481
482 /**
Matthew Barth24623522017-06-21 14:09:57 -0500483 * Speed increase delta
484 */
485 uint64_t _incSpeedDelta = 0;
486
487 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500488 * Speed decrease delta
489 */
490 uint64_t _decSpeedDelta = 0;
491
492 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500493 * Requested speed base
494 */
495 uint64_t _requestSpeedBase = 0;
496
497 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500498 * Speed increase delay in seconds
499 */
500 std::chrono::seconds _incDelay;
501
502 /**
503 * Speed decrease interval in seconds
504 */
505 std::chrono::seconds _decInterval;
506
507 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500508 * The increase timer object
509 */
510 phosphor::fan::util::Timer _incTimer;
511
512 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500513 * The decrease timer object
514 */
515 phosphor::fan::util::Timer _decTimer;
516
517 /**
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700518 * Event loop used on set speed event timers
Matthew Barth90149802017-08-15 10:51:37 -0500519 */
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700520 sdeventplus::Event _eventLoop;
Matthew Barth90149802017-08-15 10:51:37 -0500521
522 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500523 * The vector of fans in this zone
524 */
525 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500526
527 /**
528 * @brief Map of object property values
529 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500530 std::map<std::string,
531 std::map<std::string,
532 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500533 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500534
535 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500536 * @brief Map of active fan control allowed by groups
537 */
Matthew Barth60b00762017-08-15 13:39:06 -0500538 std::map<const Group, bool> _active;
Matthew Barth861d77c2017-05-22 14:18:25 -0500539
540 /**
Matthew Barth98726c42017-10-17 10:35:20 -0500541 * @brief Map of floor change allowed by groups
542 */
543 std::map<const Group, bool> _floorChange;
544
545 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -0600546 * @brief Map of groups controlling decreases allowed
547 */
548 std::map<const Group, bool> _decAllowed;
549
550 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500551 * @brief Map of group service names
552 */
553 std::map<const Group, std::vector<Service>> _services;
554
555 /**
Matthew Bartha603ed02018-01-19 16:56:26 -0600556 * @brief Map tree of paths to services of interfaces
557 */
558 std::map<std::string,
559 std::map<std::string,
560 std::vector<std::string>>> _servTree;
561
562 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500563 * @brief List of signal event arguments and Dbus matches for callbacks
Matthew Barth38a93a82017-05-11 14:12:27 -0500564 */
Matthew Barthf6b76d82017-08-04 12:58:02 -0500565 std::vector<SignalEvent> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500566
567 /**
Matthew Barth90149802017-08-15 10:51:37 -0500568 * @brief List of timers for events
569 */
Matthew Barthbfb1a562017-10-05 17:03:40 -0500570 std::vector<TimerEvent> _timerEvents;
Matthew Barth90149802017-08-15 10:51:37 -0500571
572 /**
Matthew Barth4e728542017-09-14 16:47:55 -0500573 * @brief Get the request speed base if defined, otherwise the
574 * the current target speed is returned
575 *
576 * @return - The request speed base or current target speed
577 */
578 inline auto getRequestSpeedBase() const
579 {
580 return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
581 };
582
583 /**
Matthew Barth34f1bda2017-05-31 13:45:36 -0500584 * @brief Dbus signal change callback handler
Matthew Barth38a93a82017-05-11 14:12:27 -0500585 *
Matthew Barth34f1bda2017-05-31 13:45:36 -0500586 * @param[in] msg - Expanded sdbusplus message data
587 * @param[in] eventData - The single event's data
Matthew Barth38a93a82017-05-11 14:12:27 -0500588 */
Matthew Barth34f1bda2017-05-31 13:45:36 -0500589 void handleEvent(sdbusplus::message::message& msg,
590 const EventData* eventData);
Matt Spinler7f88fe62017-04-10 14:39:02 -0500591};
592
593}
594}
595}