blob: 36fdb54a4fb63d1eb5ea9ece9467bcbf52868b03 [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>
Matt Spinler7f88fe62017-04-10 14:39:02 -05005#include <sdbusplus/bus.hpp>
William A. Kennington III1cfc2f12018-10-19 17:29:46 -07006#include <sdeventplus/event.hpp>
William A. Kennington III8fd879f2018-10-30 19:49:29 -07007#include <vector>
Matt Spinler7f88fe62017-04-10 14:39:02 -05008#include "fan.hpp"
9#include "types.hpp"
Matthew Barth766f8542019-01-29 12:44:13 -060010#include "sdbusplus.hpp"
Matthew Barth93af4192019-01-18 09:30:57 -060011#include "xyz/openbmc_project/Control/ThermalMode/server.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -050012
13namespace phosphor
14{
15namespace fan
16{
17namespace control
18{
19
Matthew Barth93af4192019-01-18 09:30:57 -060020using ThermalObject = sdbusplus::server::object::object<
21 sdbusplus::xyz::openbmc_project::Control::server::ThermalMode>;
22
Matt Spinler7f88fe62017-04-10 14:39:02 -050023/**
Matthew Barth14184132017-05-19 14:37:30 -050024 * The mode fan control will run in:
25 * - init - only do the initialization steps
26 * - control - run normal control algorithms
27 */
28enum class Mode
29{
30 init,
31 control
32};
33
34/**
Matt Spinler7f88fe62017-04-10 14:39:02 -050035 * @class Represents a fan control zone, which is a group of fans
36 * that behave the same.
37 */
Matthew Barth93af4192019-01-18 09:30:57 -060038class Zone : public ThermalObject
Matt Spinler7f88fe62017-04-10 14:39:02 -050039{
40 public:
41
42 Zone() = delete;
43 Zone(const Zone&) = delete;
Matthew Barth0081fdb2017-11-14 14:02:34 -060044 Zone(Zone&&) = delete;
Matt Spinler7f88fe62017-04-10 14:39:02 -050045 Zone& operator=(const Zone&) = delete;
46 Zone& operator=(Zone&&) = delete;
47 ~Zone() = default;
48
49 /**
50 * Constructor
51 * Creates the appropriate fan objects based on
52 * the zone definition data passed in.
53 *
Matthew Barth14184132017-05-19 14:37:30 -050054 * @param[in] mode - mode of fan control
Matt Spinler7f88fe62017-04-10 14:39:02 -050055 * @param[in] bus - the dbus object
Matthew Barth93af4192019-01-18 09:30:57 -060056 * @param[in] path - object instance path
William A. Kennington III1cfc2f12018-10-19 17:29:46 -070057 * @param[in] event - Event loop reference
Matt Spinler7f88fe62017-04-10 14:39:02 -050058 * @param[in] def - the fan zone definition data
59 */
Matthew Barth14184132017-05-19 14:37:30 -050060 Zone(Mode mode,
61 sdbusplus::bus::bus& bus,
Matthew Barth93af4192019-01-18 09:30:57 -060062 const std::string& path,
William A. Kennington III1cfc2f12018-10-19 17:29:46 -070063 const sdeventplus::Event& event,
Matt Spinler7f88fe62017-04-10 14:39:02 -050064 const ZoneDefinition& def);
65
66 /**
Matthew Barth016bd242018-03-07 16:06:06 -060067 * @brief Get the zone's bus
68 *
69 * @return The bus used by the zone
70 */
71 inline auto& getBus()
72 {
73 return _bus;
74 }
75
76 /**
77 * @brief Get the zone's path
78 *
79 * @return The path of this zone
80 */
81 inline auto& getPath()
82 {
83 return _path;
84 }
85
86 /**
87 * @brief Get the zone's hosted interfaces
88 *
89 * @return The interfaces hosted by this zone
90 */
91 inline auto& getIfaces()
92 {
93 return _ifaces;
94 }
95
96 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -050097 * Sets all fans in the zone to the speed
Matthew Barth60b00762017-08-15 13:39:06 -050098 * passed in when the zone is active
Matt Spinler7f88fe62017-04-10 14:39:02 -050099 *
100 * @param[in] speed - the fan speed
101 */
102 void setSpeed(uint64_t speed);
103
104 /**
Matthew Barth60b00762017-08-15 13:39:06 -0500105 * Sets the zone to full speed regardless of zone's active state
Matt Spinler7f88fe62017-04-10 14:39:02 -0500106 */
Matthew Barth60b00762017-08-15 13:39:06 -0500107 void setFullSpeed();
Matt Spinler7f88fe62017-04-10 14:39:02 -0500108
Matthew Barth38a93a82017-05-11 14:12:27 -0500109 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500110 * @brief Sets the automatic fan control allowed active state
111 *
112 * @param[in] group - A group that affects the active state
113 * @param[in] isActiveAllow - Active state according to group
114 */
115 void setActiveAllow(const Group* group, bool isActiveAllow);
116
117 /**
Matthew Barth98726c42017-10-17 10:35:20 -0500118 * @brief Sets the floor change allowed state
119 *
120 * @param[in] group - A group that affects floor changes
121 * @param[in] isAllow - Allow state according to group
122 */
123 inline void setFloorChangeAllow(const Group* group, bool isAllow)
124 {
125 _floorChange[*(group)] = isAllow;
126 }
127
128 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -0600129 * @brief Sets the decrease allowed state of a group
130 *
131 * @param[in] group - A group that affects speed decreases
132 * @param[in] isAllow - Allow state according to group
133 */
134 inline void setDecreaseAllow(const Group* group, bool isAllow)
135 {
136 _decAllowed[*(group)] = isAllow;
137 }
138
139 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600140 * @brief Sets a given object's event data for a property on this zone
141 *
142 * @param[in] object - Name of the object containing the property
143 * @param[in] interface - Interface name containing the property
144 * @param[in] property - Property name
145 * @param[in] data - Property value
146 */
147 inline void setObjectData(const std::string& object,
148 const std::string& interface,
149 const std::string& property,
150 EventData* data)
151 {
152 _objects[object][interface][property] = data;
153 }
154
155 /**
Matthew Barth38a93a82017-05-11 14:12:27 -0500156 * @brief Sets a given object's property value
157 *
158 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500159 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -0500160 * @param[in] property - Property name
161 * @param[in] value - Property value
162 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500163 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -0500164 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500165 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -0500166 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500167 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -0500168 {
Matthew Barthcec5ab72017-06-02 15:20:56 -0500169 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -0500170 };
171
Matthew Barth17d1fe22017-05-11 15:00:36 -0500172 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600173 * @brief Sets a given object's property value
174 *
175 * @param[in] object - Name of the object containing the property
176 * @param[in] interface - Interface name containing the property
177 * @param[in] property - Property name
178 * @param[in] value - Property value
179 */
180 template <typename T>
181 void setPropertyValue(const std::string& object,
182 const std::string& interface,
183 const std::string& property,
184 T value)
185 {
186 _properties[object][interface][property] = value;
187 };
188
189 /**
Matthew Barth17d1fe22017-05-11 15:00:36 -0500190 * @brief Get the value of an object's property
191 *
192 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500193 * @param[in] interface - Interface name containing the property
Matthew Barth17d1fe22017-05-11 15:00:36 -0500194 * @param[in] property - Property name
195 *
196 * @return - The property value
197 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500198 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500199 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500200 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500201 const std::string& property)
202 {
Matthew Barth9e741ed2017-06-02 16:29:09 -0500203 return sdbusplus::message::variant_ns::get<T>(
Matthew Barthbc651602017-08-10 16:59:43 -0500204 _properties.at(object).at(interface).at(property));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500205 };
206
Matthew Barth1de66622017-06-12 13:13:02 -0500207 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500208 * @brief Get the object's property variant
209 *
210 * @param[in] object - Name of the object containing the property
211 * @param[in] interface - Interface name containing the property
212 * @param[in] property - Property name
213 *
214 * @return - The property variant
215 */
216 inline auto getPropValueVariant(const std::string& object,
217 const std::string& interface,
218 const std::string& property)
219 {
220 return _properties.at(object).at(interface).at(property);
221 };
222
223 /**
Matthew Barth7f4c5482020-02-07 16:14:46 -0600224 * @brief Get a property's value after applying a set of visitors
225 * to translate the property value's type change to keep from
226 * affecting the configured use of the property.
227 *
228 * @param[in] intf = Interface name containing the property
229 * @param[in] prop = Property name
230 * @param[in] variant = Variant containing the property's value from
231 * the supported property types.
232 */
233 template <typename T>
234 inline auto getPropertyValueVisitor(
235 const char* intf,
236 const char* prop,
237 PropertyVariantType& variant)
238 {
239 T value;
240
241 // Handle the transition of the dbus sensor value type from
242 // int64 to double which also removed the scale property.
243 // https://gerrit.openbmc-project.xyz/11739
244 if (strcmp(intf, "xyz.openbmc_project.Sensor.Value") == 0 &&
245 strcmp(prop, "Value") == 0)
246 {
247 std::visit([&value](auto&& val)
248 {
249 // If the type configured is int64, but the sensor value
250 // property's type is double, scale it by 1000 and return
251 // the value as an int64 as configured.
252 using V = std::decay_t<decltype(val)>;
253 if constexpr(std::is_same_v<T, int64_t> &&
254 std::is_same_v<V, double>)
255 {
256 val = val * 1000;
257 value = static_cast<T>(val);
258 }
259 // If the type configured matches the sensor value
260 // property's type, just return the value as its
261 // given type.
262 else if constexpr((std::is_same_v<T, int64_t> &&
263 std::is_same_v<V, int64_t>) ||
264 (std::is_same_v<T, double> &&
265 std::is_same_v<V, double>))
266 {
267 value = val;
268 }
269 }, variant);
270
271 return value;
272 }
273
274 // Default to return the property's value by the data type
275 // configured, applying no visitors to the variant.
276 value = std::get<T>(variant);
277
278 return value;
279 };
280
281 /**
Matthew Barth1499a5c2018-03-20 15:52:33 -0500282 * @brief Remove an object's interface
283 *
284 * @param[in] object - Name of the object with the interface
285 * @param[in] interface - Interface name to remove
286 */
Matthew Barth30abbef2018-04-12 09:40:54 -0500287 inline void removeObjectInterface(const char* object,
288 const char* interface)
Matthew Barth1499a5c2018-03-20 15:52:33 -0500289 {
290 auto it = _properties.find(object);
291 if (it != std::end(_properties))
292 {
293 _properties[object].erase(interface);
294 }
295 }
296
297 /**
Matthew Barth55dea642017-11-06 13:34:32 -0600298 * @brief Remove a service associated to a group
299 *
300 * @param[in] group - Group associated with service
301 * @param[in] name - Service name to remove
302 */
303 void removeService(const Group* group,
304 const std::string& name);
305
306 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500307 * @brief Set or update a service name owner in use
308 *
309 * @param[in] group - Group associated with service
310 * @param[in] name - Service name
311 * @param[in] hasOwner - Whether the service is owned or not
312 */
313 void setServiceOwner(const Group* group,
314 const std::string& name,
315 const bool hasOwner);
316
317 /**
Matthew Barth480787c2017-11-06 11:00:00 -0600318 * @brief Set or update all services for a group
319 *
320 * @param[in] group - Group to get service names for
321 */
322 void setServices(const Group* group);
323
324 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500325 * @brief Get the group's list of service names
326 *
327 * @param[in] group - Group to get service names for
328 *
329 * @return - The list of service names
330 */
331 inline auto getGroupServices(const Group* group)
332 {
333 return _services.at(*group);
334 }
335
336 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500337 * @brief Initialize a set speed event properties and actions
338 *
339 * @param[in] event - Set speed event
340 */
341 void initEvent(const SetSpeedEvent& event);
342
343 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500344 * @brief Removes all the set speed event properties and actions
345 *
346 * @param[in] event - Set speed event
347 */
348 void removeEvent(const SetSpeedEvent& event);
349
350 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500351 * @brief Get the default floor speed
352 *
353 * @return - The defined default floor speed
354 */
355 inline auto getDefFloor()
356 {
357 return _defFloorSpeed;
358 };
359
Matthew Barth4af419c2017-06-12 13:39:31 -0500360 /**
Matthew Barth8d06a832019-10-02 14:43:39 -0500361 * @brief Set the default floor
362 *
363 * @param[in] speed - Speed to set the default floor to
364 */
365 inline void setDefFloor(uint64_t speed)
366 {
367 _defFloorSpeed = speed;
368 };
369
370 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500371 * @brief Get the ceiling speed
372 *
373 * @return - The current ceiling speed
374 */
375 inline auto& getCeiling() const
376 {
377 return _ceilingSpeed;
378 };
379
380 /**
381 * @brief Set the ceiling speed to the given speed
382 *
383 * @param[in] speed - Speed to set the ceiling to
384 */
385 inline void setCeiling(uint64_t speed)
386 {
387 _ceilingSpeed = speed;
388 };
389
390 /**
391 * @brief Swaps the ceiling key value with what's given and
392 * returns the value that was swapped.
393 *
394 * @param[in] keyValue - New ceiling key value
395 *
396 * @return - Ceiling key value prior to swapping
397 */
398 inline auto swapCeilingKeyValue(int64_t keyValue)
399 {
400 std::swap(_ceilingKeyValue, keyValue);
401 return keyValue;
402 };
403
Matthew Barth24623522017-06-21 14:09:57 -0500404 /**
405 * @brief Get the increase speed delta
406 *
407 * @return - The current increase speed delta
408 */
409 inline auto& getIncSpeedDelta() const
410 {
411 return _incSpeedDelta;
412 };
413
Matthew Barth240397b2017-06-22 11:23:30 -0500414 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500415 * @brief Get the decrease speed delta
416 *
417 * @return - The current decrease speed delta
418 */
419 inline auto& getDecSpeedDelta() const
420 {
421 return _decSpeedDelta;
422 };
423
424 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500425 * @brief Set the floor speed to the given speed and increase target
Matthew Barth98726c42017-10-17 10:35:20 -0500426 * speed to the floor when target is below floor where floor changes
427 * are allowed.
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500428 *
429 * @param[in] speed - Speed to set the floor to
430 */
431 void setFloor(uint64_t speed);
432
433 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500434 * @brief Set the requested speed base to be used as the speed to
435 * base a new requested speed target from
436 *
437 * @param[in] speedBase - Base speed value to use
438 */
439 inline void setRequestSpeedBase(uint64_t speedBase)
440 {
441 _requestSpeedBase = speedBase;
442 };
443
444 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500445 * @brief Calculate the requested target speed from the given delta
446 * and increase the fan speeds, not going above the ceiling.
447 *
448 * @param[in] targetDelta - The delta to increase the target speed by
449 */
450 void requestSpeedIncrease(uint64_t targetDelta);
451
Matthew Barth0ce99d82017-06-22 15:07:29 -0500452 /**
453 * @brief Calculate the requested target speed from the given delta
454 * and increase the fan speeds, not going above the ceiling.
455 *
456 * @param[in] targetDelta - The delta to increase the target speed by
457 */
458 void requestSpeedDecrease(uint64_t targetDelta);
459
Matthew Barth8600d9a2017-06-23 14:38:05 -0500460 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500461 * @brief Callback function for the increase timer that delays
462 * processing of requested speed increases while fans are increasing
463 */
464 void incTimerExpired();
465
466 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500467 * @brief Callback function for the decrease timer that processes any
468 * requested speed decreases if allowed
469 */
470 void decTimerExpired();
471
Matthew Barth90149802017-08-15 10:51:37 -0500472 /**
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700473 * @brief Get the event loop used with this zone's timers
Matthew Barthbfb1a562017-10-05 17:03:40 -0500474 *
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700475 * @return - The event loop for timers
Matthew Barthbfb1a562017-10-05 17:03:40 -0500476 */
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700477 inline auto& getEventLoop()
Matthew Barthbfb1a562017-10-05 17:03:40 -0500478 {
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700479 return _eventLoop;
Matthew Barthbfb1a562017-10-05 17:03:40 -0500480 }
481
482 /**
Matthew Barth33bfe762018-11-05 11:13:25 -0600483 * @brief Remove the given signal event
484 *
485 * @param[in] seIter - Iterator pointing to the signal event to remove
486 */
487 inline void removeSignal(std::vector<SignalEvent>::iterator& seIter)
488 {
Matthew Barth33bfe762018-11-05 11:13:25 -0600489 std::get<signalEventDataPos>(*seIter).reset();
490 if (std::get<signalMatchPos>(*seIter) != nullptr)
491 {
492 std::get<signalMatchPos>(*seIter).reset();
493 }
Matthew Barth33bfe762018-11-05 11:13:25 -0600494 }
495
496 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500497 * @brief Get the list of timer events
498 *
499 * @return - List of timer events
500 */
501 inline auto& getTimerEvents()
502 {
503 return _timerEvents;
504 }
505
506 /**
507 * @brief Find the first instance of a timer event
508 *
509 * @param[in] eventGroup - Group associated with a timer
510 * @param[in] eventActions - List of actions associated with a timer
Matthew Barthd7b716a2018-11-16 13:37:57 -0600511 * @param[in] eventTimers - List of timers to find the timer in
Matthew Barthbfb1a562017-10-05 17:03:40 -0500512 *
513 * @return - Iterator to the timer event
514 */
515 std::vector<TimerEvent>::iterator findTimer(
516 const Group& eventGroup,
Matthew Barthd7b716a2018-11-16 13:37:57 -0600517 const std::vector<Action>& eventActions,
518 std::vector<TimerEvent>& eventTimers);
Matthew Barthbfb1a562017-10-05 17:03:40 -0500519
520 /**
521 * @brief Add a timer to the list of timer based events
522 *
Matthew Barthd7b716a2018-11-16 13:37:57 -0600523 * @param[in] name - Event name associated with timer
William A. Kennington III94fe1a02018-10-30 19:00:27 -0700524 * @param[in] group - Group associated with a timer
525 * @param[in] actions - List of actions associated with a timer
526 * @param[in] tConf - Configuration for the new timer
Matthew Barthbfb1a562017-10-05 17:03:40 -0500527 */
Matthew Barthd7b716a2018-11-16 13:37:57 -0600528 void addTimer(const std::string& name,
529 const Group& group,
William A. Kennington III94fe1a02018-10-30 19:00:27 -0700530 const std::vector<Action>& actions,
531 const TimerConf& tConf);
Matthew Barthbfb1a562017-10-05 17:03:40 -0500532
533 /**
Matthew Barth90149802017-08-15 10:51:37 -0500534 * @brief Callback function for event timers that processes the given
Matthew Barthf9201ab2017-09-11 16:07:58 -0500535 * actions for a group
Matthew Barth90149802017-08-15 10:51:37 -0500536 *
Matthew Barthf9201ab2017-09-11 16:07:58 -0500537 * @param[in] eventGroup - Group to process actions on
538 * @param[in] eventActions - List of event actions to run
Matthew Barth90149802017-08-15 10:51:37 -0500539 */
William A. Kennington IIIc0c5f072018-10-30 19:11:01 -0700540 void timerExpired(const Group& eventGroup,
541 const std::vector<Action>& eventActions);
Matthew Barth90149802017-08-15 10:51:37 -0500542
Matthew Bartha603ed02018-01-19 16:56:26 -0600543 /**
544 * @brief Get the service for a given path and interface from cached
545 * dataset and add a service that's not found
546 *
547 * @param[in] path - Path to get service for
548 * @param[in] intf - Interface to get service for
549 *
550 * @return - The service name
551 */
552 const std::string& getService(const std::string& path,
553 const std::string& intf);
554
555 /**
556 * @brief Add a set of services for a path and interface
557 * by retrieving all the path subtrees to the given depth
558 * from root for the interface
559 *
560 * @param[in] path - Path to add services for
561 * @param[in] intf - Interface to add services for
562 * @param[in] depth - Depth of tree traversal from root path
563 *
564 * @return - The associated service to the given path and interface
565 * or empty string for no service found
566 */
567 const std::string& addServices(const std::string& path,
568 const std::string& intf,
569 int32_t depth);
570
Matthew Barth6faf8942019-01-22 09:26:09 -0600571 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600572 * @brief Dbus signal change callback handler
573 *
574 * @param[in] msg - Expanded sdbusplus message data
575 * @param[in] eventData - The single event's data
576 */
577 void handleEvent(sdbusplus::message::message& msg,
578 const EventData* eventData);
579
580 /**
581 * @brief Add a signal to the list of signal based events
582 *
Matthew Barth79cb8312018-11-14 15:20:31 -0600583 * @param[in] name - Event name
Matthew Barth016bd242018-03-07 16:06:06 -0600584 * @param[in] data - Event data for signal
585 * @param[in] match - Subscribed signal match
586 */
587 inline void addSignal(
Matthew Barth79cb8312018-11-14 15:20:31 -0600588 const std::string& name,
Matthew Barth016bd242018-03-07 16:06:06 -0600589 std::unique_ptr<EventData>&& data,
590 std::unique_ptr<sdbusplus::server::match::match>&& match)
591 {
Matthew Barth79cb8312018-11-14 15:20:31 -0600592 _signalEvents[name].emplace_back(std::move(data), std::move(match));
Matthew Barth016bd242018-03-07 16:06:06 -0600593 }
594
595 /**
Matthew Barth70b2e7d2019-02-18 11:03:07 -0600596 * @brief Set a property to be persisted
597 *
598 * @param[in] intf - Interface containing property
599 * @param[in] prop - Property to be persisted
600 */
601 inline void setPersisted(const std::string& intf,
602 const std::string& prop)
603 {
604 _persisted[intf].emplace_back(prop);
605 }
606
607 /**
608 * @brief Get persisted property
609 *
610 * @param[in] intf - Interface containing property
611 * @param[in] prop - Property persisted
612 *
613 * @return - True if property is to be persisted, false otherwise
614 */
615 auto getPersisted(const std::string& intf,
616 const std::string& prop);
617
618 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600619 * @brief Get a property value from the zone object or the bus when
620 * the property requested is not on the zone object
621 *
622 * @param[in] path - Path of object
623 * @param[in] intf - Object interface
624 * @param[in] prop - Object property
625 *
626 * @return - Property's value
627 */
628 template <typename T>
629 auto getPropertyByName(const std::string& path,
630 const std::string& intf,
631 const std::string& prop)
632 {
633 T value;
634 auto pathIter = _objects.find(path);
635 if (pathIter != _objects.end())
636 {
637 auto intfIter = pathIter->second.find(intf);
638 if (intfIter != pathIter->second.end())
639 {
640 if (intf == "xyz.openbmc_project.Control.ThermalMode")
641 {
642 auto var = ThermalMode::getPropertyByName(prop);
643 // Use visitor to determine if requested property
644 // type(T) is available on this interface and read it
645 std::visit([&value](auto&& val)
646 {
647 using V = std::decay_t<decltype(val)>;
648 if constexpr(std::is_same_v<T, V>)
649 {
650 value = val;
651 }
652 }, var);
653
654 return value;
655 }
656 }
657 }
658
Matthew Barth7f4c5482020-02-07 16:14:46 -0600659 // Retrieve the property's value applying any visitors necessary
Matthew Barth766f8542019-01-29 12:44:13 -0600660 auto service = getService(path, intf);
Matthew Barth7f4c5482020-02-07 16:14:46 -0600661 auto variant =
662 util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
663 _bus, service, path, intf, prop);
664 value = getPropertyValueVisitor<T>(
665 intf.c_str(), prop.c_str(), variant);
Matthew Barth766f8542019-01-29 12:44:13 -0600666
667 return value;
668 };
669
670 /**
Matthew Barth6faf8942019-01-22 09:26:09 -0600671 * @brief Overridden thermal object's set 'Current' property function
672 *
673 * @param[in] value - Value to set 'Current' to
674 *
675 * @return - The updated value of the 'Current' property
676 */
677 virtual std::string current(std::string value);
678
Matt Spinler7f88fe62017-04-10 14:39:02 -0500679 private:
680
681 /**
682 * The dbus object
683 */
684 sdbusplus::bus::bus& _bus;
685
686 /**
Matthew Barth93af4192019-01-18 09:30:57 -0600687 * Zone object path
688 */
689 const std::string _path;
690
691 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600692 * Zone supported interfaces
693 */
694 const std::vector<std::string> _ifaces;
695
696 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500697 * Full speed for the zone
698 */
699 const uint64_t _fullSpeed;
700
701 /**
702 * The zone number
703 */
704 const size_t _zoneNum;
705
706 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500707 * The default floor speed for the zone
708 */
Matthew Barth8d06a832019-10-02 14:43:39 -0500709 uint64_t _defFloorSpeed;
Matthew Barth1de66622017-06-12 13:13:02 -0500710
711 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500712 * The default ceiling speed for the zone
713 */
714 const uint64_t _defCeilingSpeed;
715
716 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500717 * The floor speed to not go below
718 */
719 uint64_t _floorSpeed = _defFloorSpeed;
720
721 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500722 * The ceiling speed to not go above
723 */
724 uint64_t _ceilingSpeed = _defCeilingSpeed;
725
726 /**
727 * The previous sensor value for calculating the ceiling
728 */
729 int64_t _ceilingKeyValue = 0;
730
731 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500732 * Automatic fan control active state
733 */
734 bool _isActive = true;
735
736 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500737 * Target speed for this zone
738 */
739 uint64_t _targetSpeed = _fullSpeed;
740
741 /**
Matthew Barth24623522017-06-21 14:09:57 -0500742 * Speed increase delta
743 */
744 uint64_t _incSpeedDelta = 0;
745
746 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500747 * Speed decrease delta
748 */
749 uint64_t _decSpeedDelta = 0;
750
751 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500752 * Requested speed base
753 */
754 uint64_t _requestSpeedBase = 0;
755
756 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500757 * Speed increase delay in seconds
758 */
759 std::chrono::seconds _incDelay;
760
761 /**
762 * Speed decrease interval in seconds
763 */
764 std::chrono::seconds _decInterval;
765
766 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500767 * The increase timer object
768 */
William A. Kennington III8fd879f2018-10-30 19:49:29 -0700769 Timer _incTimer;
Matthew Barth1ee48f22017-06-27 15:14:48 -0500770
771 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500772 * The decrease timer object
773 */
William A. Kennington III8fd879f2018-10-30 19:49:29 -0700774 Timer _decTimer;
Matthew Barth8600d9a2017-06-23 14:38:05 -0500775
776 /**
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700777 * Event loop used on set speed event timers
Matthew Barth90149802017-08-15 10:51:37 -0500778 */
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700779 sdeventplus::Event _eventLoop;
Matthew Barth90149802017-08-15 10:51:37 -0500780
781 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500782 * The vector of fans in this zone
783 */
784 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500785
786 /**
787 * @brief Map of object property values
788 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500789 std::map<std::string,
790 std::map<std::string,
791 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500792 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500793
794 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600795 * @brief Map of zone objects
796 */
797 std::map<std::string,
798 std::map<std::string,
799 std::map<std::string,
800 EventData*>>> _objects;
801
802 /**
Matthew Barth70b2e7d2019-02-18 11:03:07 -0600803 * @brief Map of interfaces to persisted properties
804 */
805 std::map<std::string, std::vector<std::string>> _persisted;
806
807 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500808 * @brief Map of active fan control allowed by groups
809 */
Matthew Barth60b00762017-08-15 13:39:06 -0500810 std::map<const Group, bool> _active;
Matthew Barth861d77c2017-05-22 14:18:25 -0500811
812 /**
Matthew Barth98726c42017-10-17 10:35:20 -0500813 * @brief Map of floor change allowed by groups
814 */
815 std::map<const Group, bool> _floorChange;
816
817 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -0600818 * @brief Map of groups controlling decreases allowed
819 */
820 std::map<const Group, bool> _decAllowed;
821
822 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500823 * @brief Map of group service names
824 */
825 std::map<const Group, std::vector<Service>> _services;
826
827 /**
Matthew Bartha603ed02018-01-19 16:56:26 -0600828 * @brief Map tree of paths to services of interfaces
829 */
830 std::map<std::string,
831 std::map<std::string,
832 std::vector<std::string>>> _servTree;
833
834 /**
Matthew Barth79cb8312018-11-14 15:20:31 -0600835 * @brief List of signal event arguments and Dbus matches
836 * for callbacks per event name
Matthew Barth38a93a82017-05-11 14:12:27 -0500837 */
Matthew Barth79cb8312018-11-14 15:20:31 -0600838 std::map<std::string, std::vector<SignalEvent>> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500839
840 /**
Matthew Barthd7b716a2018-11-16 13:37:57 -0600841 * @brief List of timers per event name
Matthew Barth90149802017-08-15 10:51:37 -0500842 */
Matthew Barthd7b716a2018-11-16 13:37:57 -0600843 std::map<std::string, std::vector<TimerEvent>> _timerEvents;
Matthew Barth90149802017-08-15 10:51:37 -0500844
845 /**
Matthew Barthcc8912e2019-01-21 11:35:27 -0600846 * @brief Save the thermal control current mode property
847 * to persisted storage
848 */
849 void saveCurrentMode();
850
851 /**
Matthew Barth9e4db252019-01-21 13:08:02 -0600852 * @brief Restore persisted thermal control current mode property
853 * value, setting the mode to "Default" otherwise
854 */
855 void restoreCurrentMode();
856
857 /**
Matthew Barth4e728542017-09-14 16:47:55 -0500858 * @brief Get the request speed base if defined, otherwise the
859 * the current target speed is returned
860 *
861 * @return - The request speed base or current target speed
862 */
863 inline auto getRequestSpeedBase() const
864 {
865 return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
866 };
Matt Spinler7f88fe62017-04-10 14:39:02 -0500867};
868
869}
870}
871}