blob: a56b1c711df164cdaccbccd6d230f4e85e7c61e4 [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
60 * passed in
61 *
62 * @param[in] speed - the fan speed
63 */
64 void setSpeed(uint64_t speed);
65
66 /**
67 * Sets the zone to full speed
68 */
69 inline void setFullSpeed()
70 {
71 if (_fullSpeed != 0)
72 {
73 setSpeed(_fullSpeed);
74 }
75 }
76
Matthew Barth38a93a82017-05-11 14:12:27 -050077 /**
Matthew Barth861d77c2017-05-22 14:18:25 -050078 * @brief Sets the automatic fan control allowed active state
79 *
80 * @param[in] group - A group that affects the active state
81 * @param[in] isActiveAllow - Active state according to group
82 */
83 void setActiveAllow(const Group* group, bool isActiveAllow);
84
85 /**
Matthew Barth38a93a82017-05-11 14:12:27 -050086 * @brief Sets a given object's property value
87 *
88 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -050089 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -050090 * @param[in] property - Property name
91 * @param[in] value - Property value
92 */
Matthew Barth9e741ed2017-06-02 16:29:09 -050093 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -050094 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -050095 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -050096 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -050097 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -050098 {
Matthew Barthcec5ab72017-06-02 15:20:56 -050099 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -0500100 };
101
Matthew Barth17d1fe22017-05-11 15:00:36 -0500102 /**
103 * @brief Get the value of an object's property
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 Barth17d1fe22017-05-11 15:00:36 -0500107 * @param[in] property - Property name
108 *
109 * @return - The property value
110 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500111 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500112 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500113 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500114 const std::string& property)
115 {
Matthew Barth9e741ed2017-06-02 16:29:09 -0500116 return sdbusplus::message::variant_ns::get<T>(
Matthew Barthbc651602017-08-10 16:59:43 -0500117 _properties.at(object).at(interface).at(property));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500118 };
119
Matthew Barth1de66622017-06-12 13:13:02 -0500120 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500121 * @brief Get the object's property variant
122 *
123 * @param[in] object - Name of the object containing the property
124 * @param[in] interface - Interface name containing the property
125 * @param[in] property - Property name
126 *
127 * @return - The property variant
128 */
129 inline auto getPropValueVariant(const std::string& object,
130 const std::string& interface,
131 const std::string& property)
132 {
133 return _properties.at(object).at(interface).at(property);
134 };
135
136 /**
137 * @brief Initialize a set speed event properties and actions
138 *
139 * @param[in] event - Set speed event
140 */
141 void initEvent(const SetSpeedEvent& event);
142
143 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500144 * @brief Removes all the set speed event properties and actions
145 *
146 * @param[in] event - Set speed event
147 */
148 void removeEvent(const SetSpeedEvent& event);
149
150 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500151 * @brief Get the default floor speed
152 *
153 * @return - The defined default floor speed
154 */
155 inline auto getDefFloor()
156 {
157 return _defFloorSpeed;
158 };
159
Matthew Barth4af419c2017-06-12 13:39:31 -0500160 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500161 * @brief Get the ceiling speed
162 *
163 * @return - The current ceiling speed
164 */
165 inline auto& getCeiling() const
166 {
167 return _ceilingSpeed;
168 };
169
170 /**
171 * @brief Set the ceiling speed to the given speed
172 *
173 * @param[in] speed - Speed to set the ceiling to
174 */
175 inline void setCeiling(uint64_t speed)
176 {
177 _ceilingSpeed = speed;
178 };
179
180 /**
181 * @brief Swaps the ceiling key value with what's given and
182 * returns the value that was swapped.
183 *
184 * @param[in] keyValue - New ceiling key value
185 *
186 * @return - Ceiling key value prior to swapping
187 */
188 inline auto swapCeilingKeyValue(int64_t keyValue)
189 {
190 std::swap(_ceilingKeyValue, keyValue);
191 return keyValue;
192 };
193
Matthew Barth24623522017-06-21 14:09:57 -0500194 /**
195 * @brief Get the increase speed delta
196 *
197 * @return - The current increase speed delta
198 */
199 inline auto& getIncSpeedDelta() const
200 {
201 return _incSpeedDelta;
202 };
203
Matthew Barth240397b2017-06-22 11:23:30 -0500204 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500205 * @brief Get the decrease speed delta
206 *
207 * @return - The current decrease speed delta
208 */
209 inline auto& getDecSpeedDelta() const
210 {
211 return _decSpeedDelta;
212 };
213
214 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500215 * @brief Set the floor speed to the given speed and increase target
216 * speed to the floor when target is below floor.
217 *
218 * @param[in] speed - Speed to set the floor to
219 */
220 void setFloor(uint64_t speed);
221
222 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500223 * @brief Calculate the requested target speed from the given delta
224 * and increase the fan speeds, not going above the ceiling.
225 *
226 * @param[in] targetDelta - The delta to increase the target speed by
227 */
228 void requestSpeedIncrease(uint64_t targetDelta);
229
Matthew Barth0ce99d82017-06-22 15:07:29 -0500230 /**
231 * @brief Calculate the requested target speed from the given delta
232 * and increase the fan speeds, not going above the ceiling.
233 *
234 * @param[in] targetDelta - The delta to increase the target speed by
235 */
236 void requestSpeedDecrease(uint64_t targetDelta);
237
Matthew Barth8600d9a2017-06-23 14:38:05 -0500238 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500239 * @brief Callback function for the increase timer that delays
240 * processing of requested speed increases while fans are increasing
241 */
242 void incTimerExpired();
243
244 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500245 * @brief Callback function for the decrease timer that processes any
246 * requested speed decreases if allowed
247 */
248 void decTimerExpired();
249
Matt Spinler7f88fe62017-04-10 14:39:02 -0500250 private:
251
252 /**
253 * The dbus object
254 */
255 sdbusplus::bus::bus& _bus;
256
257 /**
258 * Full speed for the zone
259 */
260 const uint64_t _fullSpeed;
261
262 /**
263 * The zone number
264 */
265 const size_t _zoneNum;
266
267 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500268 * The default floor speed for the zone
269 */
270 const uint64_t _defFloorSpeed;
271
272 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500273 * The default ceiling speed for the zone
274 */
275 const uint64_t _defCeilingSpeed;
276
277 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500278 * The floor speed to not go below
279 */
280 uint64_t _floorSpeed = _defFloorSpeed;
281
282 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500283 * The ceiling speed to not go above
284 */
285 uint64_t _ceilingSpeed = _defCeilingSpeed;
286
287 /**
288 * The previous sensor value for calculating the ceiling
289 */
290 int64_t _ceilingKeyValue = 0;
291
292 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500293 * Automatic fan control active state
294 */
295 bool _isActive = true;
296
297 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500298 * Target speed for this zone
299 */
300 uint64_t _targetSpeed = _fullSpeed;
301
302 /**
Matthew Barth24623522017-06-21 14:09:57 -0500303 * Speed increase delta
304 */
305 uint64_t _incSpeedDelta = 0;
306
307 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500308 * Speed decrease delta
309 */
310 uint64_t _decSpeedDelta = 0;
311
312 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500313 * Speed increase delay in seconds
314 */
315 std::chrono::seconds _incDelay;
316
317 /**
318 * Speed decrease interval in seconds
319 */
320 std::chrono::seconds _decInterval;
321
322 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500323 * The increase timer object
324 */
325 phosphor::fan::util::Timer _incTimer;
326
327 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500328 * The decrease timer object
329 */
330 phosphor::fan::util::Timer _decTimer;
331
332 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500333 * The vector of fans in this zone
334 */
335 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500336
337 /**
338 * @brief Map of object property values
339 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500340 std::map<std::string,
341 std::map<std::string,
342 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500343 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500344
345 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500346 * @brief Map of active fan control allowed by groups
347 */
348 std::map<const Group*, bool> _active;
349
350 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500351 * @brief List of signal event arguments and Dbus matches for callbacks
Matthew Barth38a93a82017-05-11 14:12:27 -0500352 */
Matthew Barthf6b76d82017-08-04 12:58:02 -0500353 std::vector<SignalEvent> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500354
355 /**
Matthew Barth1bf0ce42017-06-23 16:16:30 -0500356 * @brief Refresh the given property's cached value
357 *
358 * @param[in] bus - the bus to use
359 * @param[in] path - the dbus path name
360 * @param[in] iface - the dbus interface name
361 * @param[in] prop - the property name
362 */
363 void refreshProperty(sdbusplus::bus::bus& bus,
364 const std::string& path,
365 const std::string& iface,
366 const std::string& prop);
367
368 /**
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500369 * @brief Get a property value from the path/interface given
370 *
371 * @param[in] bus - the bus to use
372 * @param[in] path - the dbus path name
373 * @param[in] iface - the dbus interface name
374 * @param[in] prop - the property name
375 * @param[out] value - the value of the property
376 */
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500377 static void getProperty(sdbusplus::bus::bus& bus,
378 const std::string& path,
379 const std::string& iface,
380 const std::string& prop,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500381 PropertyVariantType& value);
Matthew Barthdf3e8d62017-05-31 11:07:24 -0500382
383 /**
Matthew Barth34f1bda2017-05-31 13:45:36 -0500384 * @brief Dbus signal change callback handler
Matthew Barth38a93a82017-05-11 14:12:27 -0500385 *
Matthew Barth34f1bda2017-05-31 13:45:36 -0500386 * @param[in] msg - Expanded sdbusplus message data
387 * @param[in] eventData - The single event's data
Matthew Barth38a93a82017-05-11 14:12:27 -0500388 */
Matthew Barth34f1bda2017-05-31 13:45:36 -0500389 void handleEvent(sdbusplus::message::message& msg,
390 const EventData* eventData);
Matt Spinler7f88fe62017-04-10 14:39:02 -0500391};
392
393}
394}
395}