blob: c949228a1faca0770a3d0d93fc1bfb8295b49999 [file] [log] [blame]
Matt Spinler7f88fe62017-04-10 14:39:02 -05001#pragma once
William A. Kennington III8fd879f2018-10-30 19:49:29 -07002#include <algorithm>
William A. Kennington III2c8e1982018-11-12 08:37:07 -08003#include <cassert>
Matthew Bartha9561842017-06-29 11:43:45 -05004#include <chrono>
Patrick Williamsed7b0342020-02-12 10:29:46 -06005#include <cmath>
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>
William A. Kennington III8fd879f2018-10-30 19:49:29 -07008#include <vector>
Matt Spinler7f88fe62017-04-10 14:39:02 -05009#include "fan.hpp"
10#include "types.hpp"
Matthew Barth766f8542019-01-29 12:44:13 -060011#include "sdbusplus.hpp"
Matthew Barth93af4192019-01-18 09:30:57 -060012#include "xyz/openbmc_project/Control/ThermalMode/server.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -050013
14namespace phosphor
15{
16namespace fan
17{
18namespace control
19{
20
Matthew Barth93af4192019-01-18 09:30:57 -060021using ThermalObject = sdbusplus::server::object::object<
22 sdbusplus::xyz::openbmc_project::Control::server::ThermalMode>;
23
Matt Spinler7f88fe62017-04-10 14:39:02 -050024/**
Matthew Barth14184132017-05-19 14:37:30 -050025 * The mode fan control will run in:
26 * - init - only do the initialization steps
27 * - control - run normal control algorithms
28 */
29enum class Mode
30{
31 init,
32 control
33};
34
35/**
Matt Spinler7f88fe62017-04-10 14:39:02 -050036 * @class Represents a fan control zone, which is a group of fans
37 * that behave the same.
38 */
Matthew Barth93af4192019-01-18 09:30:57 -060039class Zone : public ThermalObject
Matt Spinler7f88fe62017-04-10 14:39:02 -050040{
41 public:
42
43 Zone() = delete;
44 Zone(const Zone&) = delete;
Matthew Barth0081fdb2017-11-14 14:02:34 -060045 Zone(Zone&&) = delete;
Matt Spinler7f88fe62017-04-10 14:39:02 -050046 Zone& operator=(const Zone&) = delete;
47 Zone& operator=(Zone&&) = delete;
48 ~Zone() = default;
49
50 /**
51 * Constructor
52 * Creates the appropriate fan objects based on
53 * the zone definition data passed in.
54 *
Matthew Barth14184132017-05-19 14:37:30 -050055 * @param[in] mode - mode of fan control
Matt Spinler7f88fe62017-04-10 14:39:02 -050056 * @param[in] bus - the dbus object
Matthew Barth93af4192019-01-18 09:30:57 -060057 * @param[in] path - object instance path
William A. Kennington III1cfc2f12018-10-19 17:29:46 -070058 * @param[in] event - Event loop reference
Matt Spinler7f88fe62017-04-10 14:39:02 -050059 * @param[in] def - the fan zone definition data
60 */
Matthew Barth14184132017-05-19 14:37:30 -050061 Zone(Mode mode,
62 sdbusplus::bus::bus& bus,
Matthew Barth93af4192019-01-18 09:30:57 -060063 const std::string& path,
William A. Kennington III1cfc2f12018-10-19 17:29:46 -070064 const sdeventplus::Event& event,
Matt Spinler7f88fe62017-04-10 14:39:02 -050065 const ZoneDefinition& def);
66
67 /**
Matthew Barth016bd242018-03-07 16:06:06 -060068 * @brief Get the zone's bus
69 *
70 * @return The bus used by the zone
71 */
72 inline auto& getBus()
73 {
74 return _bus;
75 }
76
77 /**
78 * @brief Get the zone's path
79 *
80 * @return The path of this zone
81 */
82 inline auto& getPath()
83 {
84 return _path;
85 }
86
87 /**
88 * @brief Get the zone's hosted interfaces
89 *
90 * @return The interfaces hosted by this zone
91 */
92 inline auto& getIfaces()
93 {
94 return _ifaces;
95 }
96
97 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -050098 * Sets all fans in the zone to the speed
Matthew Barth60b00762017-08-15 13:39:06 -050099 * passed in when the zone is active
Matt Spinler7f88fe62017-04-10 14:39:02 -0500100 *
101 * @param[in] speed - the fan speed
102 */
103 void setSpeed(uint64_t speed);
104
105 /**
Matthew Barth60b00762017-08-15 13:39:06 -0500106 * Sets the zone to full speed regardless of zone's active state
Matt Spinler7f88fe62017-04-10 14:39:02 -0500107 */
Matthew Barth60b00762017-08-15 13:39:06 -0500108 void setFullSpeed();
Matt Spinler7f88fe62017-04-10 14:39:02 -0500109
Matthew Barth38a93a82017-05-11 14:12:27 -0500110 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500111 * @brief Sets the automatic fan control allowed active state
112 *
113 * @param[in] group - A group that affects the active state
114 * @param[in] isActiveAllow - Active state according to group
115 */
116 void setActiveAllow(const Group* group, bool isActiveAllow);
117
118 /**
Matthew Barth98726c42017-10-17 10:35:20 -0500119 * @brief Sets the floor change allowed state
120 *
121 * @param[in] group - A group that affects floor changes
122 * @param[in] isAllow - Allow state according to group
123 */
124 inline void setFloorChangeAllow(const Group* group, bool isAllow)
125 {
126 _floorChange[*(group)] = isAllow;
127 }
128
129 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -0600130 * @brief Sets the decrease allowed state of a group
131 *
132 * @param[in] group - A group that affects speed decreases
133 * @param[in] isAllow - Allow state according to group
134 */
135 inline void setDecreaseAllow(const Group* group, bool isAllow)
136 {
137 _decAllowed[*(group)] = isAllow;
138 }
139
140 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600141 * @brief Sets a given object's event data for a property on this zone
142 *
143 * @param[in] object - Name of the object containing the property
144 * @param[in] interface - Interface name containing the property
145 * @param[in] property - Property name
146 * @param[in] data - Property value
147 */
148 inline void setObjectData(const std::string& object,
149 const std::string& interface,
150 const std::string& property,
151 EventData* data)
152 {
153 _objects[object][interface][property] = data;
154 }
155
156 /**
Matthew Barth38a93a82017-05-11 14:12:27 -0500157 * @brief Sets a given object's property value
158 *
159 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500160 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -0500161 * @param[in] property - Property name
162 * @param[in] value - Property value
163 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500164 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -0500165 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500166 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -0500167 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500168 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -0500169 {
Matthew Barthcec5ab72017-06-02 15:20:56 -0500170 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -0500171 };
172
Matthew Barth17d1fe22017-05-11 15:00:36 -0500173 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600174 * @brief Sets a given object's property value
175 *
176 * @param[in] object - Name of the object containing the property
177 * @param[in] interface - Interface name containing the property
178 * @param[in] property - Property name
179 * @param[in] value - Property value
180 */
181 template <typename T>
182 void setPropertyValue(const std::string& object,
183 const std::string& interface,
184 const std::string& property,
185 T value)
186 {
187 _properties[object][interface][property] = value;
188 };
189
190 /**
Matthew Barth17d1fe22017-05-11 15:00:36 -0500191 * @brief Get the value of an object's property
192 *
193 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500194 * @param[in] interface - Interface name containing the property
Matthew Barth17d1fe22017-05-11 15:00:36 -0500195 * @param[in] property - Property name
196 *
197 * @return - The property value
198 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500199 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500200 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500201 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500202 const std::string& property)
203 {
Matthew Barth9e741ed2017-06-02 16:29:09 -0500204 return sdbusplus::message::variant_ns::get<T>(
Matthew Barthbc651602017-08-10 16:59:43 -0500205 _properties.at(object).at(interface).at(property));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500206 };
207
Matthew Barth1de66622017-06-12 13:13:02 -0500208 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500209 * @brief Get the object's property variant
210 *
211 * @param[in] object - Name of the object containing the property
212 * @param[in] interface - Interface name containing the property
213 * @param[in] property - Property name
214 *
215 * @return - The property variant
216 */
217 inline auto getPropValueVariant(const std::string& object,
218 const std::string& interface,
219 const std::string& property)
220 {
221 return _properties.at(object).at(interface).at(property);
222 };
223
224 /**
Matthew Barth7f4c5482020-02-07 16:14:46 -0600225 * @brief Get a property's value after applying a set of visitors
226 * to translate the property value's type change to keep from
227 * affecting the configured use of the property.
228 *
229 * @param[in] intf = Interface name containing the property
230 * @param[in] prop = Property name
231 * @param[in] variant = Variant containing the property's value from
232 * the supported property types.
233 */
234 template <typename T>
235 inline auto getPropertyValueVisitor(
236 const char* intf,
237 const char* prop,
238 PropertyVariantType& variant)
239 {
240 T value;
241
242 // Handle the transition of the dbus sensor value type from
243 // int64 to double which also removed the scale property.
244 // https://gerrit.openbmc-project.xyz/11739
245 if (strcmp(intf, "xyz.openbmc_project.Sensor.Value") == 0 &&
246 strcmp(prop, "Value") == 0)
247 {
248 std::visit([&value](auto&& val)
249 {
250 // If the type configured is int64, but the sensor value
251 // property's type is double, scale it by 1000 and return
252 // the value as an int64 as configured.
253 using V = std::decay_t<decltype(val)>;
254 if constexpr(std::is_same_v<T, int64_t> &&
255 std::is_same_v<V, double>)
256 {
257 val = val * 1000;
Patrick Williamsed7b0342020-02-12 10:29:46 -0600258 value = std::lround(val);
Matthew Barth7f4c5482020-02-07 16:14:46 -0600259 }
260 // If the type configured matches the sensor value
261 // property's type, just return the value as its
262 // given type.
263 else if constexpr((std::is_same_v<T, int64_t> &&
264 std::is_same_v<V, int64_t>) ||
265 (std::is_same_v<T, double> &&
266 std::is_same_v<V, double>))
267 {
268 value = val;
269 }
270 }, variant);
271
272 return value;
273 }
274
275 // Default to return the property's value by the data type
276 // configured, applying no visitors to the variant.
277 value = std::get<T>(variant);
278
279 return value;
280 };
281
282 /**
Matthew Barth1499a5c2018-03-20 15:52:33 -0500283 * @brief Remove an object's interface
284 *
285 * @param[in] object - Name of the object with the interface
286 * @param[in] interface - Interface name to remove
287 */
Matthew Barth30abbef2018-04-12 09:40:54 -0500288 inline void removeObjectInterface(const char* object,
289 const char* interface)
Matthew Barth1499a5c2018-03-20 15:52:33 -0500290 {
291 auto it = _properties.find(object);
292 if (it != std::end(_properties))
293 {
294 _properties[object].erase(interface);
295 }
296 }
297
298 /**
Matthew Barth55dea642017-11-06 13:34:32 -0600299 * @brief Remove a service associated to a group
300 *
301 * @param[in] group - Group associated with service
302 * @param[in] name - Service name to remove
303 */
304 void removeService(const Group* group,
305 const std::string& name);
306
307 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500308 * @brief Set or update a service name owner in use
309 *
310 * @param[in] group - Group associated with service
311 * @param[in] name - Service name
312 * @param[in] hasOwner - Whether the service is owned or not
313 */
314 void setServiceOwner(const Group* group,
315 const std::string& name,
316 const bool hasOwner);
317
318 /**
Matthew Barth480787c2017-11-06 11:00:00 -0600319 * @brief Set or update all services for a group
320 *
321 * @param[in] group - Group to get service names for
322 */
323 void setServices(const Group* group);
324
325 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500326 * @brief Get the group's list of service names
327 *
328 * @param[in] group - Group to get service names for
329 *
330 * @return - The list of service names
331 */
332 inline auto getGroupServices(const Group* group)
333 {
334 return _services.at(*group);
335 }
336
337 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500338 * @brief Initialize a set speed event properties and actions
339 *
340 * @param[in] event - Set speed event
341 */
342 void initEvent(const SetSpeedEvent& event);
343
344 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500345 * @brief Removes all the set speed event properties and actions
346 *
347 * @param[in] event - Set speed event
348 */
349 void removeEvent(const SetSpeedEvent& event);
350
351 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500352 * @brief Get the default floor speed
353 *
354 * @return - The defined default floor speed
355 */
356 inline auto getDefFloor()
357 {
358 return _defFloorSpeed;
359 };
360
Matthew Barth4af419c2017-06-12 13:39:31 -0500361 /**
Matthew Barth8d06a832019-10-02 14:43:39 -0500362 * @brief Set the default floor
363 *
364 * @param[in] speed - Speed to set the default floor to
365 */
366 inline void setDefFloor(uint64_t speed)
367 {
368 _defFloorSpeed = speed;
369 };
370
371 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500372 * @brief Get the ceiling speed
373 *
374 * @return - The current ceiling speed
375 */
376 inline auto& getCeiling() const
377 {
378 return _ceilingSpeed;
379 };
380
381 /**
382 * @brief Set the ceiling speed to the given speed
383 *
384 * @param[in] speed - Speed to set the ceiling to
385 */
386 inline void setCeiling(uint64_t speed)
387 {
388 _ceilingSpeed = speed;
389 };
390
391 /**
392 * @brief Swaps the ceiling key value with what's given and
393 * returns the value that was swapped.
394 *
395 * @param[in] keyValue - New ceiling key value
396 *
397 * @return - Ceiling key value prior to swapping
398 */
399 inline auto swapCeilingKeyValue(int64_t keyValue)
400 {
401 std::swap(_ceilingKeyValue, keyValue);
402 return keyValue;
403 };
404
Matthew Barth24623522017-06-21 14:09:57 -0500405 /**
406 * @brief Get the increase speed delta
407 *
408 * @return - The current increase speed delta
409 */
410 inline auto& getIncSpeedDelta() const
411 {
412 return _incSpeedDelta;
413 };
414
Matthew Barth240397b2017-06-22 11:23:30 -0500415 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500416 * @brief Get the decrease speed delta
417 *
418 * @return - The current decrease speed delta
419 */
420 inline auto& getDecSpeedDelta() const
421 {
422 return _decSpeedDelta;
423 };
424
425 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500426 * @brief Set the floor speed to the given speed and increase target
Matthew Barth98726c42017-10-17 10:35:20 -0500427 * speed to the floor when target is below floor where floor changes
428 * are allowed.
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500429 *
430 * @param[in] speed - Speed to set the floor to
431 */
432 void setFloor(uint64_t speed);
433
434 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500435 * @brief Set the requested speed base to be used as the speed to
436 * base a new requested speed target from
437 *
438 * @param[in] speedBase - Base speed value to use
439 */
440 inline void setRequestSpeedBase(uint64_t speedBase)
441 {
442 _requestSpeedBase = speedBase;
443 };
444
445 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500446 * @brief Calculate the requested target speed from the given delta
447 * and increase the fan speeds, not going above the ceiling.
448 *
449 * @param[in] targetDelta - The delta to increase the target speed by
450 */
451 void requestSpeedIncrease(uint64_t targetDelta);
452
Matthew Barth0ce99d82017-06-22 15:07:29 -0500453 /**
454 * @brief Calculate the requested target speed from the given delta
455 * and increase the fan speeds, not going above the ceiling.
456 *
457 * @param[in] targetDelta - The delta to increase the target speed by
458 */
459 void requestSpeedDecrease(uint64_t targetDelta);
460
Matthew Barth8600d9a2017-06-23 14:38:05 -0500461 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500462 * @brief Callback function for the increase timer that delays
463 * processing of requested speed increases while fans are increasing
464 */
465 void incTimerExpired();
466
467 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500468 * @brief Callback function for the decrease timer that processes any
469 * requested speed decreases if allowed
470 */
471 void decTimerExpired();
472
Matthew Barth90149802017-08-15 10:51:37 -0500473 /**
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700474 * @brief Get the event loop used with this zone's timers
Matthew Barthbfb1a562017-10-05 17:03:40 -0500475 *
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700476 * @return - The event loop for timers
Matthew Barthbfb1a562017-10-05 17:03:40 -0500477 */
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700478 inline auto& getEventLoop()
Matthew Barthbfb1a562017-10-05 17:03:40 -0500479 {
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700480 return _eventLoop;
Matthew Barthbfb1a562017-10-05 17:03:40 -0500481 }
482
483 /**
Matthew Barth33bfe762018-11-05 11:13:25 -0600484 * @brief Remove the given signal event
485 *
486 * @param[in] seIter - Iterator pointing to the signal event to remove
487 */
488 inline void removeSignal(std::vector<SignalEvent>::iterator& seIter)
489 {
Matthew Barth33bfe762018-11-05 11:13:25 -0600490 std::get<signalEventDataPos>(*seIter).reset();
491 if (std::get<signalMatchPos>(*seIter) != nullptr)
492 {
493 std::get<signalMatchPos>(*seIter).reset();
494 }
Matthew Barth33bfe762018-11-05 11:13:25 -0600495 }
496
497 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500498 * @brief Get the list of timer events
499 *
500 * @return - List of timer events
501 */
502 inline auto& getTimerEvents()
503 {
504 return _timerEvents;
505 }
506
507 /**
508 * @brief Find the first instance of a timer event
509 *
510 * @param[in] eventGroup - Group associated with a timer
511 * @param[in] eventActions - List of actions associated with a timer
Matthew Barthd7b716a2018-11-16 13:37:57 -0600512 * @param[in] eventTimers - List of timers to find the timer in
Matthew Barthbfb1a562017-10-05 17:03:40 -0500513 *
514 * @return - Iterator to the timer event
515 */
516 std::vector<TimerEvent>::iterator findTimer(
517 const Group& eventGroup,
Matthew Barthd7b716a2018-11-16 13:37:57 -0600518 const std::vector<Action>& eventActions,
519 std::vector<TimerEvent>& eventTimers);
Matthew Barthbfb1a562017-10-05 17:03:40 -0500520
521 /**
522 * @brief Add a timer to the list of timer based events
523 *
Matthew Barthd7b716a2018-11-16 13:37:57 -0600524 * @param[in] name - Event name associated with timer
William A. Kennington III94fe1a02018-10-30 19:00:27 -0700525 * @param[in] group - Group associated with a timer
526 * @param[in] actions - List of actions associated with a timer
527 * @param[in] tConf - Configuration for the new timer
Matthew Barthbfb1a562017-10-05 17:03:40 -0500528 */
Matthew Barthd7b716a2018-11-16 13:37:57 -0600529 void addTimer(const std::string& name,
530 const Group& group,
William A. Kennington III94fe1a02018-10-30 19:00:27 -0700531 const std::vector<Action>& actions,
532 const TimerConf& tConf);
Matthew Barthbfb1a562017-10-05 17:03:40 -0500533
534 /**
Matthew Barth90149802017-08-15 10:51:37 -0500535 * @brief Callback function for event timers that processes the given
Matthew Barthf9201ab2017-09-11 16:07:58 -0500536 * actions for a group
Matthew Barth90149802017-08-15 10:51:37 -0500537 *
Matthew Barthf9201ab2017-09-11 16:07:58 -0500538 * @param[in] eventGroup - Group to process actions on
539 * @param[in] eventActions - List of event actions to run
Matthew Barth90149802017-08-15 10:51:37 -0500540 */
William A. Kennington IIIc0c5f072018-10-30 19:11:01 -0700541 void timerExpired(const Group& eventGroup,
542 const std::vector<Action>& eventActions);
Matthew Barth90149802017-08-15 10:51:37 -0500543
Matthew Bartha603ed02018-01-19 16:56:26 -0600544 /**
545 * @brief Get the service for a given path and interface from cached
546 * dataset and add a service that's not found
547 *
548 * @param[in] path - Path to get service for
549 * @param[in] intf - Interface to get service for
550 *
551 * @return - The service name
552 */
553 const std::string& getService(const std::string& path,
554 const std::string& intf);
555
556 /**
557 * @brief Add a set of services for a path and interface
558 * by retrieving all the path subtrees to the given depth
559 * from root for the interface
560 *
561 * @param[in] path - Path to add services for
562 * @param[in] intf - Interface to add services for
563 * @param[in] depth - Depth of tree traversal from root path
564 *
565 * @return - The associated service to the given path and interface
566 * or empty string for no service found
567 */
568 const std::string& addServices(const std::string& path,
569 const std::string& intf,
570 int32_t depth);
571
Matthew Barth6faf8942019-01-22 09:26:09 -0600572 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600573 * @brief Dbus signal change callback handler
574 *
575 * @param[in] msg - Expanded sdbusplus message data
576 * @param[in] eventData - The single event's data
577 */
578 void handleEvent(sdbusplus::message::message& msg,
579 const EventData* eventData);
580
581 /**
582 * @brief Add a signal to the list of signal based events
583 *
Matthew Barth79cb8312018-11-14 15:20:31 -0600584 * @param[in] name - Event name
Matthew Barth016bd242018-03-07 16:06:06 -0600585 * @param[in] data - Event data for signal
586 * @param[in] match - Subscribed signal match
587 */
588 inline void addSignal(
Matthew Barth79cb8312018-11-14 15:20:31 -0600589 const std::string& name,
Matthew Barth016bd242018-03-07 16:06:06 -0600590 std::unique_ptr<EventData>&& data,
591 std::unique_ptr<sdbusplus::server::match::match>&& match)
592 {
Matthew Barth79cb8312018-11-14 15:20:31 -0600593 _signalEvents[name].emplace_back(std::move(data), std::move(match));
Matthew Barth016bd242018-03-07 16:06:06 -0600594 }
595
596 /**
Matthew Barth70b2e7d2019-02-18 11:03:07 -0600597 * @brief Set a property to be persisted
598 *
599 * @param[in] intf - Interface containing property
600 * @param[in] prop - Property to be persisted
601 */
602 inline void setPersisted(const std::string& intf,
603 const std::string& prop)
604 {
605 _persisted[intf].emplace_back(prop);
606 }
607
608 /**
609 * @brief Get persisted property
610 *
611 * @param[in] intf - Interface containing property
612 * @param[in] prop - Property persisted
613 *
614 * @return - True if property is to be persisted, false otherwise
615 */
616 auto getPersisted(const std::string& intf,
617 const std::string& prop);
618
619 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600620 * @brief Get a property value from the zone object or the bus when
621 * the property requested is not on the zone object
622 *
623 * @param[in] path - Path of object
624 * @param[in] intf - Object interface
625 * @param[in] prop - Object property
626 *
627 * @return - Property's value
628 */
629 template <typename T>
630 auto getPropertyByName(const std::string& path,
631 const std::string& intf,
632 const std::string& prop)
633 {
634 T value;
635 auto pathIter = _objects.find(path);
636 if (pathIter != _objects.end())
637 {
638 auto intfIter = pathIter->second.find(intf);
639 if (intfIter != pathIter->second.end())
640 {
641 if (intf == "xyz.openbmc_project.Control.ThermalMode")
642 {
643 auto var = ThermalMode::getPropertyByName(prop);
644 // Use visitor to determine if requested property
645 // type(T) is available on this interface and read it
646 std::visit([&value](auto&& val)
647 {
648 using V = std::decay_t<decltype(val)>;
649 if constexpr(std::is_same_v<T, V>)
650 {
651 value = val;
652 }
653 }, var);
654
655 return value;
656 }
657 }
658 }
659
Matthew Barth7f4c5482020-02-07 16:14:46 -0600660 // Retrieve the property's value applying any visitors necessary
Matthew Barth766f8542019-01-29 12:44:13 -0600661 auto service = getService(path, intf);
Matthew Barth7f4c5482020-02-07 16:14:46 -0600662 auto variant =
663 util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
664 _bus, service, path, intf, prop);
665 value = getPropertyValueVisitor<T>(
666 intf.c_str(), prop.c_str(), variant);
Matthew Barth766f8542019-01-29 12:44:13 -0600667
668 return value;
669 };
670
671 /**
Matthew Barth6faf8942019-01-22 09:26:09 -0600672 * @brief Overridden thermal object's set 'Current' property function
673 *
674 * @param[in] value - Value to set 'Current' to
675 *
676 * @return - The updated value of the 'Current' property
677 */
678 virtual std::string current(std::string value);
679
Matt Spinler7f88fe62017-04-10 14:39:02 -0500680 private:
681
682 /**
683 * The dbus object
684 */
685 sdbusplus::bus::bus& _bus;
686
687 /**
Matthew Barth93af4192019-01-18 09:30:57 -0600688 * Zone object path
689 */
690 const std::string _path;
691
692 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600693 * Zone supported interfaces
694 */
695 const std::vector<std::string> _ifaces;
696
697 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500698 * Full speed for the zone
699 */
700 const uint64_t _fullSpeed;
701
702 /**
703 * The zone number
704 */
705 const size_t _zoneNum;
706
707 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500708 * The default floor speed for the zone
709 */
Matthew Barth8d06a832019-10-02 14:43:39 -0500710 uint64_t _defFloorSpeed;
Matthew Barth1de66622017-06-12 13:13:02 -0500711
712 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500713 * The default ceiling speed for the zone
714 */
715 const uint64_t _defCeilingSpeed;
716
717 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500718 * The floor speed to not go below
719 */
720 uint64_t _floorSpeed = _defFloorSpeed;
721
722 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500723 * The ceiling speed to not go above
724 */
725 uint64_t _ceilingSpeed = _defCeilingSpeed;
726
727 /**
728 * The previous sensor value for calculating the ceiling
729 */
730 int64_t _ceilingKeyValue = 0;
731
732 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500733 * Automatic fan control active state
734 */
735 bool _isActive = true;
736
737 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500738 * Target speed for this zone
739 */
740 uint64_t _targetSpeed = _fullSpeed;
741
742 /**
Matthew Barth24623522017-06-21 14:09:57 -0500743 * Speed increase delta
744 */
745 uint64_t _incSpeedDelta = 0;
746
747 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500748 * Speed decrease delta
749 */
750 uint64_t _decSpeedDelta = 0;
751
752 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500753 * Requested speed base
754 */
755 uint64_t _requestSpeedBase = 0;
756
757 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500758 * Speed increase delay in seconds
759 */
760 std::chrono::seconds _incDelay;
761
762 /**
763 * Speed decrease interval in seconds
764 */
765 std::chrono::seconds _decInterval;
766
767 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500768 * The increase timer object
769 */
William A. Kennington III8fd879f2018-10-30 19:49:29 -0700770 Timer _incTimer;
Matthew Barth1ee48f22017-06-27 15:14:48 -0500771
772 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500773 * The decrease timer object
774 */
William A. Kennington III8fd879f2018-10-30 19:49:29 -0700775 Timer _decTimer;
Matthew Barth8600d9a2017-06-23 14:38:05 -0500776
777 /**
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700778 * Event loop used on set speed event timers
Matthew Barth90149802017-08-15 10:51:37 -0500779 */
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700780 sdeventplus::Event _eventLoop;
Matthew Barth90149802017-08-15 10:51:37 -0500781
782 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500783 * The vector of fans in this zone
784 */
785 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500786
787 /**
788 * @brief Map of object property values
789 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500790 std::map<std::string,
791 std::map<std::string,
792 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500793 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500794
795 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600796 * @brief Map of zone objects
797 */
798 std::map<std::string,
799 std::map<std::string,
800 std::map<std::string,
801 EventData*>>> _objects;
802
803 /**
Matthew Barth70b2e7d2019-02-18 11:03:07 -0600804 * @brief Map of interfaces to persisted properties
805 */
806 std::map<std::string, std::vector<std::string>> _persisted;
807
808 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500809 * @brief Map of active fan control allowed by groups
810 */
Matthew Barth60b00762017-08-15 13:39:06 -0500811 std::map<const Group, bool> _active;
Matthew Barth861d77c2017-05-22 14:18:25 -0500812
813 /**
Matthew Barth98726c42017-10-17 10:35:20 -0500814 * @brief Map of floor change allowed by groups
815 */
816 std::map<const Group, bool> _floorChange;
817
818 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -0600819 * @brief Map of groups controlling decreases allowed
820 */
821 std::map<const Group, bool> _decAllowed;
822
823 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500824 * @brief Map of group service names
825 */
826 std::map<const Group, std::vector<Service>> _services;
827
828 /**
Matthew Bartha603ed02018-01-19 16:56:26 -0600829 * @brief Map tree of paths to services of interfaces
830 */
831 std::map<std::string,
832 std::map<std::string,
833 std::vector<std::string>>> _servTree;
834
835 /**
Matthew Barth79cb8312018-11-14 15:20:31 -0600836 * @brief List of signal event arguments and Dbus matches
837 * for callbacks per event name
Matthew Barth38a93a82017-05-11 14:12:27 -0500838 */
Matthew Barth79cb8312018-11-14 15:20:31 -0600839 std::map<std::string, std::vector<SignalEvent>> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500840
841 /**
Matthew Barthd7b716a2018-11-16 13:37:57 -0600842 * @brief List of timers per event name
Matthew Barth90149802017-08-15 10:51:37 -0500843 */
Matthew Barthd7b716a2018-11-16 13:37:57 -0600844 std::map<std::string, std::vector<TimerEvent>> _timerEvents;
Matthew Barth90149802017-08-15 10:51:37 -0500845
846 /**
Matthew Barthcc8912e2019-01-21 11:35:27 -0600847 * @brief Save the thermal control current mode property
848 * to persisted storage
849 */
850 void saveCurrentMode();
851
852 /**
Matthew Barth9e4db252019-01-21 13:08:02 -0600853 * @brief Restore persisted thermal control current mode property
854 * value, setting the mode to "Default" otherwise
855 */
856 void restoreCurrentMode();
857
858 /**
Matthew Barth4e728542017-09-14 16:47:55 -0500859 * @brief Get the request speed base if defined, otherwise the
860 * the current target speed is returned
861 *
862 * @return - The request speed base or current target speed
863 */
864 inline auto getRequestSpeedBase() const
865 {
866 return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
867 };
Matt Spinler7f88fe62017-04-10 14:39:02 -0500868};
869
870}
871}
872}