blob: 9c0803288c91f2304a2528889efb091cf52bf6ca [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 Barthe0ca13e2017-06-13 16:29:09 -05004#include <algorithm>
Matt Spinler7f88fe62017-04-10 14:39:02 -05005#include <sdbusplus/bus.hpp>
6#include "fan.hpp"
7#include "types.hpp"
Matthew Barth8600d9a2017-06-23 14:38:05 -05008#include "timer.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -05009
10namespace phosphor
11{
12namespace fan
13{
14namespace control
15{
16
17/**
Matthew Barth14184132017-05-19 14:37:30 -050018 * The mode fan control will run in:
19 * - init - only do the initialization steps
20 * - control - run normal control algorithms
21 */
22enum class Mode
23{
24 init,
25 control
26};
27
28/**
Matt Spinler7f88fe62017-04-10 14:39:02 -050029 * @class Represents a fan control zone, which is a group of fans
30 * that behave the same.
31 */
32class Zone
33{
34 public:
35
36 Zone() = delete;
37 Zone(const Zone&) = delete;
38 Zone(Zone&&) = default;
39 Zone& operator=(const Zone&) = delete;
40 Zone& operator=(Zone&&) = delete;
41 ~Zone() = default;
42
43 /**
44 * Constructor
45 * Creates the appropriate fan objects based on
46 * the zone definition data passed in.
47 *
Matthew Barth14184132017-05-19 14:37:30 -050048 * @param[in] mode - mode of fan control
Matt Spinler7f88fe62017-04-10 14:39:02 -050049 * @param[in] bus - the dbus object
Matthew Barth8600d9a2017-06-23 14:38:05 -050050 * @param[in] events - sd_event pointer
Matt Spinler7f88fe62017-04-10 14:39:02 -050051 * @param[in] def - the fan zone definition data
52 */
Matthew Barth14184132017-05-19 14:37:30 -050053 Zone(Mode mode,
54 sdbusplus::bus::bus& bus,
Matthew Barth8600d9a2017-06-23 14:38:05 -050055 phosphor::fan::event::EventPtr& events,
Matt Spinler7f88fe62017-04-10 14:39:02 -050056 const ZoneDefinition& def);
57
58 /**
59 * Sets all fans in the zone to the speed
Matthew Barth60b00762017-08-15 13:39:06 -050060 * passed in when the zone is active
Matt Spinler7f88fe62017-04-10 14:39:02 -050061 *
62 * @param[in] speed - the fan speed
63 */
64 void setSpeed(uint64_t speed);
65
66 /**
Matthew Barth60b00762017-08-15 13:39:06 -050067 * Sets the zone to full speed regardless of zone's active state
Matt Spinler7f88fe62017-04-10 14:39:02 -050068 */
Matthew Barth60b00762017-08-15 13:39:06 -050069 void setFullSpeed();
Matt Spinler7f88fe62017-04-10 14:39:02 -050070
Matthew Barth38a93a82017-05-11 14:12:27 -050071 /**
Matthew Barth861d77c2017-05-22 14:18:25 -050072 * @brief Sets the automatic fan control allowed active state
73 *
74 * @param[in] group - A group that affects the active state
75 * @param[in] isActiveAllow - Active state according to group
76 */
77 void setActiveAllow(const Group* group, bool isActiveAllow);
78
79 /**
Matthew Barth38a93a82017-05-11 14:12:27 -050080 * @brief Sets a given object's property value
81 *
82 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -050083 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -050084 * @param[in] property - Property name
85 * @param[in] value - Property value
86 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050087 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -050088 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -050089 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -050090 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -050091 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -050092 {
Matthew Barthcec5ab72017-06-02 15:20:56 -050093 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -050094 };
95
Matthew Barth17d1fe22017-05-11 15:00:36 -050096 /**
97 * @brief Get the value of an object's property
98 *
99 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500100 * @param[in] interface - Interface name containing the property
Matthew Barth17d1fe22017-05-11 15:00:36 -0500101 * @param[in] property - Property name
102 *
103 * @return - The property value
104 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500105 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500106 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500107 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500108 const std::string& property)
109 {
Matthew Barth9e741ed2017-06-02 16:29:09 -0500110 return sdbusplus::message::variant_ns::get<T>(
Matthew Barthbc651602017-08-10 16:59:43 -0500111 _properties.at(object).at(interface).at(property));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500112 };
113
Matthew Barth1de66622017-06-12 13:13:02 -0500114 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500115 * @brief Get the object's property variant
116 *
117 * @param[in] object - Name of the object containing the property
118 * @param[in] interface - Interface name containing the property
119 * @param[in] property - Property name
120 *
121 * @return - The property variant
122 */
123 inline auto getPropValueVariant(const std::string& object,
124 const std::string& interface,
125 const std::string& property)
126 {
127 return _properties.at(object).at(interface).at(property);
128 };
129
130 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500131 * @brief Set or update a service name owner in use
132 *
133 * @param[in] group - Group associated with service
134 * @param[in] name - Service name
135 * @param[in] hasOwner - Whether the service is owned or not
136 */
137 void setServiceOwner(const Group* group,
138 const std::string& name,
139 const bool hasOwner);
140
141 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500142 * @brief Initialize a set speed event properties and actions
143 *
144 * @param[in] event - Set speed event
145 */
146 void initEvent(const SetSpeedEvent& event);
147
148 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500149 * @brief Removes all the set speed event properties and actions
150 *
151 * @param[in] event - Set speed event
152 */
153 void removeEvent(const SetSpeedEvent& event);
154
155 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500156 * @brief Get the default floor speed
157 *
158 * @return - The defined default floor speed
159 */
160 inline auto getDefFloor()
161 {
162 return _defFloorSpeed;
163 };
164
Matthew Barth4af419c2017-06-12 13:39:31 -0500165 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500166 * @brief Get the ceiling speed
167 *
168 * @return - The current ceiling speed
169 */
170 inline auto& getCeiling() const
171 {
172 return _ceilingSpeed;
173 };
174
175 /**
176 * @brief Set the ceiling speed to the given speed
177 *
178 * @param[in] speed - Speed to set the ceiling to
179 */
180 inline void setCeiling(uint64_t speed)
181 {
182 _ceilingSpeed = speed;
183 };
184
185 /**
186 * @brief Swaps the ceiling key value with what's given and
187 * returns the value that was swapped.
188 *
189 * @param[in] keyValue - New ceiling key value
190 *
191 * @return - Ceiling key value prior to swapping
192 */
193 inline auto swapCeilingKeyValue(int64_t keyValue)
194 {
195 std::swap(_ceilingKeyValue, keyValue);
196 return keyValue;
197 };
198
Matthew Barth24623522017-06-21 14:09:57 -0500199 /**
200 * @brief Get the increase speed delta
201 *
202 * @return - The current increase speed delta
203 */
204 inline auto& getIncSpeedDelta() const
205 {
206 return _incSpeedDelta;
207 };
208
Matthew Barth240397b2017-06-22 11:23:30 -0500209 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500210 * @brief Get the decrease speed delta
211 *
212 * @return - The current decrease speed delta
213 */
214 inline auto& getDecSpeedDelta() const
215 {
216 return _decSpeedDelta;
217 };
218
219 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500220 * @brief Set the floor speed to the given speed and increase target
221 * speed to the floor when target is below floor.
222 *
223 * @param[in] speed - Speed to set the floor to
224 */
225 void setFloor(uint64_t speed);
226
227 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500228 * @brief Set the requested speed base to be used as the speed to
229 * base a new requested speed target from
230 *
231 * @param[in] speedBase - Base speed value to use
232 */
233 inline void setRequestSpeedBase(uint64_t speedBase)
234 {
235 _requestSpeedBase = speedBase;
236 };
237
238 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500239 * @brief Calculate the requested target speed from the given delta
240 * and increase the fan speeds, not going above the ceiling.
241 *
242 * @param[in] targetDelta - The delta to increase the target speed by
243 */
244 void requestSpeedIncrease(uint64_t targetDelta);
245
Matthew Barth0ce99d82017-06-22 15:07:29 -0500246 /**
247 * @brief Calculate the requested target speed from the given delta
248 * and increase the fan speeds, not going above the ceiling.
249 *
250 * @param[in] targetDelta - The delta to increase the target speed by
251 */
252 void requestSpeedDecrease(uint64_t targetDelta);
253
Matthew Barth8600d9a2017-06-23 14:38:05 -0500254 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500255 * @brief Callback function for the increase timer that delays
256 * processing of requested speed increases while fans are increasing
257 */
258 void incTimerExpired();
259
260 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500261 * @brief Callback function for the decrease timer that processes any
262 * requested speed decreases if allowed
263 */
264 void decTimerExpired();
265
Matthew Barth90149802017-08-15 10:51:37 -0500266 /**
267 * @brief Callback function for event timers that processes the given
Matthew Barthf9201ab2017-09-11 16:07:58 -0500268 * actions for a group
Matthew Barth90149802017-08-15 10:51:37 -0500269 *
Matthew Barthf9201ab2017-09-11 16:07:58 -0500270 * @param[in] eventGroup - Group to process actions on
271 * @param[in] eventActions - List of event actions to run
Matthew Barth90149802017-08-15 10:51:37 -0500272 */
Matthew Barthf9201ab2017-09-11 16:07:58 -0500273 void timerExpired(Group eventGroup, std::vector<Action> eventActions);
Matthew Barth90149802017-08-15 10:51:37 -0500274
Matt Spinler7f88fe62017-04-10 14:39:02 -0500275 private:
276
277 /**
278 * The dbus object
279 */
280 sdbusplus::bus::bus& _bus;
281
282 /**
283 * Full speed for the zone
284 */
285 const uint64_t _fullSpeed;
286
287 /**
288 * The zone number
289 */
290 const size_t _zoneNum;
291
292 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500293 * The default floor speed for the zone
294 */
295 const uint64_t _defFloorSpeed;
296
297 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500298 * The default ceiling speed for the zone
299 */
300 const uint64_t _defCeilingSpeed;
301
302 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500303 * The floor speed to not go below
304 */
305 uint64_t _floorSpeed = _defFloorSpeed;
306
307 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500308 * The ceiling speed to not go above
309 */
310 uint64_t _ceilingSpeed = _defCeilingSpeed;
311
312 /**
313 * The previous sensor value for calculating the ceiling
314 */
315 int64_t _ceilingKeyValue = 0;
316
317 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500318 * Automatic fan control active state
319 */
320 bool _isActive = true;
321
322 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500323 * Target speed for this zone
324 */
325 uint64_t _targetSpeed = _fullSpeed;
326
327 /**
Matthew Barth24623522017-06-21 14:09:57 -0500328 * Speed increase delta
329 */
330 uint64_t _incSpeedDelta = 0;
331
332 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500333 * Speed decrease delta
334 */
335 uint64_t _decSpeedDelta = 0;
336
337 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500338 * Requested speed base
339 */
340 uint64_t _requestSpeedBase = 0;
341
342 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500343 * Speed increase delay in seconds
344 */
345 std::chrono::seconds _incDelay;
346
347 /**
348 * Speed decrease interval in seconds
349 */
350 std::chrono::seconds _decInterval;
351
352 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500353 * The increase timer object
354 */
355 phosphor::fan::util::Timer _incTimer;
356
357 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500358 * The decrease timer object
359 */
360 phosphor::fan::util::Timer _decTimer;
361
362 /**
Matthew Barth90149802017-08-15 10:51:37 -0500363 * Dbus event used on set speed event timers
364 */
365 phosphor::fan::event::EventPtr& _sdEvents;
366
367 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500368 * The vector of fans in this zone
369 */
370 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500371
372 /**
373 * @brief Map of object property values
374 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500375 std::map<std::string,
376 std::map<std::string,
377 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500378 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500379
380 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500381 * @brief Map of active fan control allowed by groups
382 */
Matthew Barth60b00762017-08-15 13:39:06 -0500383 std::map<const Group, bool> _active;
Matthew Barth861d77c2017-05-22 14:18:25 -0500384
385 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500386 * @brief Map of group service names
387 */
388 std::map<const Group, std::vector<Service>> _services;
389
390 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500391 * @brief List of signal event arguments and Dbus matches for callbacks
Matthew Barth38a93a82017-05-11 14:12:27 -0500392 */
Matthew Barthf6b76d82017-08-04 12:58:02 -0500393 std::vector<SignalEvent> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500394
395 /**
Matthew Barth90149802017-08-15 10:51:37 -0500396 * @brief List of timers for events
397 */
398 std::vector<std::unique_ptr<phosphor::fan::util::Timer>> _timerEvents;
399
400 /**
Matthew Barth4e728542017-09-14 16:47:55 -0500401 * @brief Get the request speed base if defined, otherwise the
402 * the current target speed is returned
403 *
404 * @return - The request speed base or current target speed
405 */
406 inline auto getRequestSpeedBase() const
407 {
408 return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
409 };
410
411 /**
Matthew Barth34f1bda2017-05-31 13:45:36 -0500412 * @brief Dbus signal change callback handler
Matthew Barth38a93a82017-05-11 14:12:27 -0500413 *
Matthew Barth34f1bda2017-05-31 13:45:36 -0500414 * @param[in] msg - Expanded sdbusplus message data
415 * @param[in] eventData - The single event's data
Matthew Barth38a93a82017-05-11 14:12:27 -0500416 */
Matthew Barth34f1bda2017-05-31 13:45:36 -0500417 void handleEvent(sdbusplus::message::message& msg,
418 const EventData* eventData);
Matt Spinler7f88fe62017-04-10 14:39:02 -0500419};
420
421}
422}
423}