blob: 1fdeaf2f5782d92bb570fdc1fb23f47264556d61 [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;
39 Zone(Zone&&) = default;
40 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 Barth38a93a82017-05-11 14:12:27 -050081 * @brief Sets a given object's property value
82 *
83 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -050084 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -050085 * @param[in] property - Property name
86 * @param[in] value - Property value
87 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050088 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -050089 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -050090 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -050091 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -050092 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -050093 {
Matthew Barthcec5ab72017-06-02 15:20:56 -050094 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -050095 };
96
Matthew Barth17d1fe22017-05-11 15:00:36 -050097 /**
98 * @brief Get the value of an object's property
99 *
100 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500101 * @param[in] interface - Interface name containing the property
Matthew Barth17d1fe22017-05-11 15:00:36 -0500102 * @param[in] property - Property name
103 *
104 * @return - The property value
105 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500106 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500107 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500108 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500109 const std::string& property)
110 {
Matthew Barth9e741ed2017-06-02 16:29:09 -0500111 return sdbusplus::message::variant_ns::get<T>(
Matthew Barthbc651602017-08-10 16:59:43 -0500112 _properties.at(object).at(interface).at(property));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500113 };
114
Matthew Barth1de66622017-06-12 13:13:02 -0500115 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500116 * @brief Get the object's property variant
117 *
118 * @param[in] object - Name of the object containing the property
119 * @param[in] interface - Interface name containing the property
120 * @param[in] property - Property name
121 *
122 * @return - The property variant
123 */
124 inline auto getPropValueVariant(const std::string& object,
125 const std::string& interface,
126 const std::string& property)
127 {
128 return _properties.at(object).at(interface).at(property);
129 };
130
131 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500132 * @brief Set or update a service name owner in use
133 *
134 * @param[in] group - Group associated with service
135 * @param[in] name - Service name
136 * @param[in] hasOwner - Whether the service is owned or not
137 */
138 void setServiceOwner(const Group* group,
139 const std::string& name,
140 const bool hasOwner);
141
142 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500143 * @brief Get the group's list of service names
144 *
145 * @param[in] group - Group to get service names for
146 *
147 * @return - The list of service names
148 */
149 inline auto getGroupServices(const Group* group)
150 {
151 return _services.at(*group);
152 }
153
154 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500155 * @brief Initialize a set speed event properties and actions
156 *
157 * @param[in] event - Set speed event
158 */
159 void initEvent(const SetSpeedEvent& event);
160
161 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500162 * @brief Removes all the set speed event properties and actions
163 *
164 * @param[in] event - Set speed event
165 */
166 void removeEvent(const SetSpeedEvent& event);
167
168 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500169 * @brief Get the default floor speed
170 *
171 * @return - The defined default floor speed
172 */
173 inline auto getDefFloor()
174 {
175 return _defFloorSpeed;
176 };
177
Matthew Barth4af419c2017-06-12 13:39:31 -0500178 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500179 * @brief Get the ceiling speed
180 *
181 * @return - The current ceiling speed
182 */
183 inline auto& getCeiling() const
184 {
185 return _ceilingSpeed;
186 };
187
188 /**
189 * @brief Set the ceiling speed to the given speed
190 *
191 * @param[in] speed - Speed to set the ceiling to
192 */
193 inline void setCeiling(uint64_t speed)
194 {
195 _ceilingSpeed = speed;
196 };
197
198 /**
199 * @brief Swaps the ceiling key value with what's given and
200 * returns the value that was swapped.
201 *
202 * @param[in] keyValue - New ceiling key value
203 *
204 * @return - Ceiling key value prior to swapping
205 */
206 inline auto swapCeilingKeyValue(int64_t keyValue)
207 {
208 std::swap(_ceilingKeyValue, keyValue);
209 return keyValue;
210 };
211
Matthew Barth24623522017-06-21 14:09:57 -0500212 /**
213 * @brief Get the increase speed delta
214 *
215 * @return - The current increase speed delta
216 */
217 inline auto& getIncSpeedDelta() const
218 {
219 return _incSpeedDelta;
220 };
221
Matthew Barth240397b2017-06-22 11:23:30 -0500222 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500223 * @brief Get the decrease speed delta
224 *
225 * @return - The current decrease speed delta
226 */
227 inline auto& getDecSpeedDelta() const
228 {
229 return _decSpeedDelta;
230 };
231
232 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500233 * @brief Set the floor speed to the given speed and increase target
234 * speed to the floor when target is below floor.
235 *
236 * @param[in] speed - Speed to set the floor to
237 */
238 void setFloor(uint64_t speed);
239
240 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500241 * @brief Set the requested speed base to be used as the speed to
242 * base a new requested speed target from
243 *
244 * @param[in] speedBase - Base speed value to use
245 */
246 inline void setRequestSpeedBase(uint64_t speedBase)
247 {
248 _requestSpeedBase = speedBase;
249 };
250
251 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500252 * @brief Calculate the requested target speed from the given delta
253 * and increase the fan speeds, not going above the ceiling.
254 *
255 * @param[in] targetDelta - The delta to increase the target speed by
256 */
257 void requestSpeedIncrease(uint64_t targetDelta);
258
Matthew Barth0ce99d82017-06-22 15:07:29 -0500259 /**
260 * @brief Calculate the requested target speed from the given delta
261 * and increase the fan speeds, not going above the ceiling.
262 *
263 * @param[in] targetDelta - The delta to increase the target speed by
264 */
265 void requestSpeedDecrease(uint64_t targetDelta);
266
Matthew Barth8600d9a2017-06-23 14:38:05 -0500267 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500268 * @brief Callback function for the increase timer that delays
269 * processing of requested speed increases while fans are increasing
270 */
271 void incTimerExpired();
272
273 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500274 * @brief Callback function for the decrease timer that processes any
275 * requested speed decreases if allowed
276 */
277 void decTimerExpired();
278
Matthew Barth90149802017-08-15 10:51:37 -0500279 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500280 * @brief Get the event pointer used with this zone's timers
281 *
282 * @return - The Dbus event pointer for timers
283 */
284 inline auto& getEventPtr()
285 {
286 return _sdEvents;
287 }
288
289 /**
290 * @brief Get the list of timer events
291 *
292 * @return - List of timer events
293 */
294 inline auto& getTimerEvents()
295 {
296 return _timerEvents;
297 }
298
299 /**
300 * @brief Find the first instance of a timer event
301 *
302 * @param[in] eventGroup - Group associated with a timer
303 * @param[in] eventActions - List of actions associated with a timer
304 *
305 * @return - Iterator to the timer event
306 */
307 std::vector<TimerEvent>::iterator findTimer(
308 const Group& eventGroup,
309 const std::vector<Action>& eventActions);
310
311 /**
312 * @brief Add a timer to the list of timer based events
313 *
314 * @param[in] data - Event data for timer
315 * @param[in] timer - Timer to be added
316 */
317 inline void addTimer(
318 std::unique_ptr<EventData>&& data,
319 std::unique_ptr<phosphor::fan::util::Timer>&& timer)
320 {
321 _timerEvents.emplace_back(std::move(data), std::move(timer));
322 };
323
324 /**
325 * @brief Remove the given timer event
326 *
327 * @param[in] teIter - Iterator pointing to the timer event to remove
328 */
329 inline void removeTimer(std::vector<TimerEvent>::iterator& teIter)
330 {
331 assert(teIter != std::end(_timerEvents));
332 std::get<timerEventDataPos>(*teIter).reset();
333 std::get<timerTimerPos>(*teIter).reset();
334 _timerEvents.erase(teIter);
335 }
336
337 /**
Matthew Barth90149802017-08-15 10:51:37 -0500338 * @brief Callback function for event timers that processes the given
Matthew Barthf9201ab2017-09-11 16:07:58 -0500339 * actions for a group
Matthew Barth90149802017-08-15 10:51:37 -0500340 *
Matthew Barthf9201ab2017-09-11 16:07:58 -0500341 * @param[in] eventGroup - Group to process actions on
342 * @param[in] eventActions - List of event actions to run
Matthew Barth90149802017-08-15 10:51:37 -0500343 */
Matthew Barthf9201ab2017-09-11 16:07:58 -0500344 void timerExpired(Group eventGroup, std::vector<Action> eventActions);
Matthew Barth90149802017-08-15 10:51:37 -0500345
Matt Spinler7f88fe62017-04-10 14:39:02 -0500346 private:
347
348 /**
349 * The dbus object
350 */
351 sdbusplus::bus::bus& _bus;
352
353 /**
354 * Full speed for the zone
355 */
356 const uint64_t _fullSpeed;
357
358 /**
359 * The zone number
360 */
361 const size_t _zoneNum;
362
363 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500364 * The default floor speed for the zone
365 */
366 const uint64_t _defFloorSpeed;
367
368 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500369 * The default ceiling speed for the zone
370 */
371 const uint64_t _defCeilingSpeed;
372
373 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500374 * The floor speed to not go below
375 */
376 uint64_t _floorSpeed = _defFloorSpeed;
377
378 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500379 * The ceiling speed to not go above
380 */
381 uint64_t _ceilingSpeed = _defCeilingSpeed;
382
383 /**
384 * The previous sensor value for calculating the ceiling
385 */
386 int64_t _ceilingKeyValue = 0;
387
388 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500389 * Automatic fan control active state
390 */
391 bool _isActive = true;
392
393 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500394 * Target speed for this zone
395 */
396 uint64_t _targetSpeed = _fullSpeed;
397
398 /**
Matthew Barth24623522017-06-21 14:09:57 -0500399 * Speed increase delta
400 */
401 uint64_t _incSpeedDelta = 0;
402
403 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500404 * Speed decrease delta
405 */
406 uint64_t _decSpeedDelta = 0;
407
408 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500409 * Requested speed base
410 */
411 uint64_t _requestSpeedBase = 0;
412
413 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500414 * Speed increase delay in seconds
415 */
416 std::chrono::seconds _incDelay;
417
418 /**
419 * Speed decrease interval in seconds
420 */
421 std::chrono::seconds _decInterval;
422
423 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500424 * The increase timer object
425 */
426 phosphor::fan::util::Timer _incTimer;
427
428 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500429 * The decrease timer object
430 */
431 phosphor::fan::util::Timer _decTimer;
432
433 /**
Matthew Barth90149802017-08-15 10:51:37 -0500434 * Dbus event used on set speed event timers
435 */
436 phosphor::fan::event::EventPtr& _sdEvents;
437
438 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500439 * The vector of fans in this zone
440 */
441 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500442
443 /**
444 * @brief Map of object property values
445 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500446 std::map<std::string,
447 std::map<std::string,
448 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500449 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500450
451 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500452 * @brief Map of active fan control allowed by groups
453 */
Matthew Barth60b00762017-08-15 13:39:06 -0500454 std::map<const Group, bool> _active;
Matthew Barth861d77c2017-05-22 14:18:25 -0500455
456 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500457 * @brief Map of group service names
458 */
459 std::map<const Group, std::vector<Service>> _services;
460
461 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500462 * @brief List of signal event arguments and Dbus matches for callbacks
Matthew Barth38a93a82017-05-11 14:12:27 -0500463 */
Matthew Barthf6b76d82017-08-04 12:58:02 -0500464 std::vector<SignalEvent> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500465
466 /**
Matthew Barth90149802017-08-15 10:51:37 -0500467 * @brief List of timers for events
468 */
Matthew Barthbfb1a562017-10-05 17:03:40 -0500469 std::vector<TimerEvent> _timerEvents;
Matthew Barth90149802017-08-15 10:51:37 -0500470
471 /**
Matthew Barth4e728542017-09-14 16:47:55 -0500472 * @brief Get the request speed base if defined, otherwise the
473 * the current target speed is returned
474 *
475 * @return - The request speed base or current target speed
476 */
477 inline auto getRequestSpeedBase() const
478 {
479 return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
480 };
481
482 /**
Matthew Barth34f1bda2017-05-31 13:45:36 -0500483 * @brief Dbus signal change callback handler
Matthew Barth38a93a82017-05-11 14:12:27 -0500484 *
Matthew Barth34f1bda2017-05-31 13:45:36 -0500485 * @param[in] msg - Expanded sdbusplus message data
486 * @param[in] eventData - The single event's data
Matthew Barth38a93a82017-05-11 14:12:27 -0500487 */
Matthew Barth34f1bda2017-05-31 13:45:36 -0500488 void handleEvent(sdbusplus::message::message& msg,
489 const EventData* eventData);
Matt Spinler7f88fe62017-04-10 14:39:02 -0500490};
491
492}
493}
494}