blob: 71fba3247e1e1d73fc142584c107d0184511cf9e [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>
Matthew Barth5a80f3a2020-03-13 11:28:18 -05009#include <optional>
Matt Spinler7f88fe62017-04-10 14:39:02 -050010#include "fan.hpp"
11#include "types.hpp"
Matthew Barth766f8542019-01-29 12:44:13 -060012#include "sdbusplus.hpp"
Matthew Barth93af4192019-01-18 09:30:57 -060013#include "xyz/openbmc_project/Control/ThermalMode/server.hpp"
Matt Spinler7f88fe62017-04-10 14:39:02 -050014
15namespace phosphor
16{
17namespace fan
18{
19namespace control
20{
21
Matthew Barth93af4192019-01-18 09:30:57 -060022using ThermalObject = sdbusplus::server::object::object<
23 sdbusplus::xyz::openbmc_project::Control::server::ThermalMode>;
24
Matt Spinler7f88fe62017-04-10 14:39:02 -050025/**
Matthew Barth14184132017-05-19 14:37:30 -050026 * The mode fan control will run in:
27 * - init - only do the initialization steps
28 * - control - run normal control algorithms
29 */
30enum class Mode
31{
32 init,
33 control
34};
35
36/**
Matt Spinler7f88fe62017-04-10 14:39:02 -050037 * @class Represents a fan control zone, which is a group of fans
38 * that behave the same.
39 */
Matthew Barth93af4192019-01-18 09:30:57 -060040class Zone : public ThermalObject
Matt Spinler7f88fe62017-04-10 14:39:02 -050041{
42 public:
43
44 Zone() = delete;
45 Zone(const Zone&) = delete;
Matthew Barth0081fdb2017-11-14 14:02:34 -060046 Zone(Zone&&) = delete;
Matt Spinler7f88fe62017-04-10 14:39:02 -050047 Zone& operator=(const Zone&) = delete;
48 Zone& operator=(Zone&&) = delete;
49 ~Zone() = default;
50
51 /**
52 * Constructor
53 * Creates the appropriate fan objects based on
54 * the zone definition data passed in.
55 *
Matthew Barth14184132017-05-19 14:37:30 -050056 * @param[in] mode - mode of fan control
Matt Spinler7f88fe62017-04-10 14:39:02 -050057 * @param[in] bus - the dbus object
Matthew Barth93af4192019-01-18 09:30:57 -060058 * @param[in] path - object instance path
William A. Kennington III1cfc2f12018-10-19 17:29:46 -070059 * @param[in] event - Event loop reference
Matt Spinler7f88fe62017-04-10 14:39:02 -050060 * @param[in] def - the fan zone definition data
61 */
Matthew Barth14184132017-05-19 14:37:30 -050062 Zone(Mode mode,
63 sdbusplus::bus::bus& bus,
Matthew Barth93af4192019-01-18 09:30:57 -060064 const std::string& path,
William A. Kennington III1cfc2f12018-10-19 17:29:46 -070065 const sdeventplus::Event& event,
Matt Spinler7f88fe62017-04-10 14:39:02 -050066 const ZoneDefinition& def);
67
68 /**
Matthew Barth016bd242018-03-07 16:06:06 -060069 * @brief Get the zone's bus
70 *
71 * @return The bus used by the zone
72 */
73 inline auto& getBus()
74 {
75 return _bus;
76 }
77
78 /**
79 * @brief Get the zone's path
80 *
81 * @return The path of this zone
82 */
83 inline auto& getPath()
84 {
85 return _path;
86 }
87
88 /**
89 * @brief Get the zone's hosted interfaces
90 *
91 * @return The interfaces hosted by this zone
92 */
93 inline auto& getIfaces()
94 {
95 return _ifaces;
96 }
97
98 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -050099 * Sets all fans in the zone to the speed
Matthew Barth60b00762017-08-15 13:39:06 -0500100 * passed in when the zone is active
Matt Spinler7f88fe62017-04-10 14:39:02 -0500101 *
102 * @param[in] speed - the fan speed
103 */
104 void setSpeed(uint64_t speed);
105
106 /**
Matthew Barth60b00762017-08-15 13:39:06 -0500107 * Sets the zone to full speed regardless of zone's active state
Matt Spinler7f88fe62017-04-10 14:39:02 -0500108 */
Matthew Barth60b00762017-08-15 13:39:06 -0500109 void setFullSpeed();
Matt Spinler7f88fe62017-04-10 14:39:02 -0500110
Matthew Barth38a93a82017-05-11 14:12:27 -0500111 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500112 * @brief Sets the automatic fan control allowed active state
113 *
114 * @param[in] group - A group that affects the active state
115 * @param[in] isActiveAllow - Active state according to group
116 */
117 void setActiveAllow(const Group* group, bool isActiveAllow);
118
119 /**
Matthew Barth98726c42017-10-17 10:35:20 -0500120 * @brief Sets the floor change allowed state
121 *
122 * @param[in] group - A group that affects floor changes
123 * @param[in] isAllow - Allow state according to group
124 */
125 inline void setFloorChangeAllow(const Group* group, bool isAllow)
126 {
127 _floorChange[*(group)] = isAllow;
128 }
129
130 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -0600131 * @brief Sets the decrease allowed state of a group
132 *
133 * @param[in] group - A group that affects speed decreases
134 * @param[in] isAllow - Allow state according to group
135 */
136 inline void setDecreaseAllow(const Group* group, bool isAllow)
137 {
138 _decAllowed[*(group)] = isAllow;
139 }
140
141 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600142 * @brief Sets a given object's event data for a property on this zone
143 *
144 * @param[in] object - Name of the object containing the property
145 * @param[in] interface - Interface name containing the property
146 * @param[in] property - Property name
147 * @param[in] data - Property value
148 */
149 inline void setObjectData(const std::string& object,
150 const std::string& interface,
151 const std::string& property,
152 EventData* data)
153 {
154 _objects[object][interface][property] = data;
155 }
156
157 /**
Matthew Barth38a93a82017-05-11 14:12:27 -0500158 * @brief Sets a given object's property value
159 *
160 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500161 * @param[in] interface - Interface name containing the property
Matthew Barth38a93a82017-05-11 14:12:27 -0500162 * @param[in] property - Property name
163 * @param[in] value - Property value
164 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500165 template <typename T>
Matthew Barth38a93a82017-05-11 14:12:27 -0500166 void setPropertyValue(const char* object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500167 const char* interface,
Matthew Barth38a93a82017-05-11 14:12:27 -0500168 const char* property,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500169 T value)
Matthew Barth38a93a82017-05-11 14:12:27 -0500170 {
Matthew Barthcec5ab72017-06-02 15:20:56 -0500171 _properties[object][interface][property] = value;
Matthew Barth38a93a82017-05-11 14:12:27 -0500172 };
173
Matthew Barth17d1fe22017-05-11 15:00:36 -0500174 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600175 * @brief Sets a given object's property value
176 *
177 * @param[in] object - Name of the object containing the property
178 * @param[in] interface - Interface name containing the property
179 * @param[in] property - Property name
180 * @param[in] value - Property value
181 */
182 template <typename T>
183 void setPropertyValue(const std::string& object,
184 const std::string& interface,
185 const std::string& property,
186 T value)
187 {
188 _properties[object][interface][property] = value;
189 };
190
191 /**
Matthew Barth17d1fe22017-05-11 15:00:36 -0500192 * @brief Get the value of an object's property
193 *
194 * @param[in] object - Name of the object containing the property
Matthew Barthcec5ab72017-06-02 15:20:56 -0500195 * @param[in] interface - Interface name containing the property
Matthew Barth17d1fe22017-05-11 15:00:36 -0500196 * @param[in] property - Property name
197 *
198 * @return - The property value
199 */
Matthew Barth9e741ed2017-06-02 16:29:09 -0500200 template <typename T>
Matthew Barth17d1fe22017-05-11 15:00:36 -0500201 inline auto getPropertyValue(const std::string& object,
Matthew Barthcec5ab72017-06-02 15:20:56 -0500202 const std::string& interface,
Matthew Barth17d1fe22017-05-11 15:00:36 -0500203 const std::string& property)
204 {
Patrick Williams1f514fa2020-05-13 11:53:33 -0500205 return std::get<T>(
Matthew Barthbc651602017-08-10 16:59:43 -0500206 _properties.at(object).at(interface).at(property));
Matthew Barth17d1fe22017-05-11 15:00:36 -0500207 };
208
Matthew Barth1de66622017-06-12 13:13:02 -0500209 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500210 * @brief Get the object's property variant
211 *
212 * @param[in] object - Name of the object containing the property
213 * @param[in] interface - Interface name containing the property
214 * @param[in] property - Property name
215 *
216 * @return - The property variant
217 */
218 inline auto getPropValueVariant(const std::string& object,
219 const std::string& interface,
220 const std::string& property)
221 {
222 return _properties.at(object).at(interface).at(property);
223 };
224
225 /**
Matthew Barth7f4c5482020-02-07 16:14:46 -0600226 * @brief Get a property's value after applying a set of visitors
227 * to translate the property value's type change to keep from
228 * affecting the configured use of the property.
229 *
230 * @param[in] intf = Interface name containing the property
231 * @param[in] prop = Property name
232 * @param[in] variant = Variant containing the property's value from
233 * the supported property types.
234 */
235 template <typename T>
236 inline auto getPropertyValueVisitor(
237 const char* intf,
238 const char* prop,
239 PropertyVariantType& variant)
240 {
Matthew Barth7f4c5482020-02-07 16:14:46 -0600241 // 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 {
Matthew Barth5a80f3a2020-03-13 11:28:18 -0500247 // Use 'optional' variable to determine if the sensor value
248 // is set within the visitor based on the supported types.
249 // A non-supported type configured will assert.
250 std::optional<T> value;
Matthew Barth7f4c5482020-02-07 16:14:46 -0600251 std::visit([&value](auto&& val)
252 {
253 // If the type configured is int64, but the sensor value
254 // property's type is double, scale it by 1000 and return
255 // the value as an int64 as configured.
256 using V = std::decay_t<decltype(val)>;
257 if constexpr(std::is_same_v<T, int64_t> &&
258 std::is_same_v<V, double>)
259 {
260 val = val * 1000;
Patrick Williamsed7b0342020-02-12 10:29:46 -0600261 value = std::lround(val);
Matthew Barth7f4c5482020-02-07 16:14:46 -0600262 }
263 // If the type configured matches the sensor value
264 // property's type, just return the value as its
265 // given type.
Matthew Barth5a80f3a2020-03-13 11:28:18 -0500266 else if constexpr(std::is_same_v<T, V>)
Matthew Barth7f4c5482020-02-07 16:14:46 -0600267 {
268 value = val;
269 }
270 }, variant);
271
Matthew Barth5a80f3a2020-03-13 11:28:18 -0500272 // Unable to return Sensor Value property
273 // as given type configured.
274 assert(value);
275
276 return value.value();
Matthew Barth7f4c5482020-02-07 16:14:46 -0600277 }
278
279 // Default to return the property's value by the data type
280 // configured, applying no visitors to the variant.
Matthew Barth5a80f3a2020-03-13 11:28:18 -0500281 return std::get<T>(variant);
Matthew Barth7f4c5482020-02-07 16:14:46 -0600282 };
283
284 /**
Matthew Barth1499a5c2018-03-20 15:52:33 -0500285 * @brief Remove an object's interface
286 *
287 * @param[in] object - Name of the object with the interface
288 * @param[in] interface - Interface name to remove
289 */
Matthew Barth30abbef2018-04-12 09:40:54 -0500290 inline void removeObjectInterface(const char* object,
291 const char* interface)
Matthew Barth1499a5c2018-03-20 15:52:33 -0500292 {
293 auto it = _properties.find(object);
294 if (it != std::end(_properties))
295 {
296 _properties[object].erase(interface);
297 }
298 }
299
300 /**
Matthew Barth55dea642017-11-06 13:34:32 -0600301 * @brief Remove a service associated to a group
302 *
303 * @param[in] group - Group associated with service
304 * @param[in] name - Service name to remove
305 */
306 void removeService(const Group* group,
307 const std::string& name);
308
309 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500310 * @brief Set or update a service name owner in use
311 *
312 * @param[in] group - Group associated with service
313 * @param[in] name - Service name
314 * @param[in] hasOwner - Whether the service is owned or not
315 */
316 void setServiceOwner(const Group* group,
317 const std::string& name,
318 const bool hasOwner);
319
320 /**
Matthew Barth480787c2017-11-06 11:00:00 -0600321 * @brief Set or update all services for a group
322 *
323 * @param[in] group - Group to get service names for
324 */
325 void setServices(const Group* group);
326
327 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500328 * @brief Get the group's list of service names
329 *
330 * @param[in] group - Group to get service names for
331 *
332 * @return - The list of service names
333 */
334 inline auto getGroupServices(const Group* group)
335 {
336 return _services.at(*group);
337 }
338
339 /**
Matthew Barth604329e2017-08-04 11:18:28 -0500340 * @brief Initialize a set speed event properties and actions
341 *
342 * @param[in] event - Set speed event
343 */
344 void initEvent(const SetSpeedEvent& event);
345
346 /**
Matthew Barthf6b76d82017-08-04 12:58:02 -0500347 * @brief Removes all the set speed event properties and actions
348 *
349 * @param[in] event - Set speed event
350 */
351 void removeEvent(const SetSpeedEvent& event);
352
353 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500354 * @brief Get the default floor speed
355 *
356 * @return - The defined default floor speed
357 */
358 inline auto getDefFloor()
359 {
360 return _defFloorSpeed;
361 };
362
Matthew Barth4af419c2017-06-12 13:39:31 -0500363 /**
Matthew Barth8d06a832019-10-02 14:43:39 -0500364 * @brief Set the default floor
365 *
366 * @param[in] speed - Speed to set the default floor to
367 */
368 inline void setDefFloor(uint64_t speed)
369 {
370 _defFloorSpeed = speed;
371 };
372
373 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500374 * @brief Get the ceiling speed
375 *
376 * @return - The current ceiling speed
377 */
378 inline auto& getCeiling() const
379 {
380 return _ceilingSpeed;
381 };
382
383 /**
384 * @brief Set the ceiling speed to the given speed
385 *
386 * @param[in] speed - Speed to set the ceiling to
387 */
388 inline void setCeiling(uint64_t speed)
389 {
390 _ceilingSpeed = speed;
391 };
392
393 /**
394 * @brief Swaps the ceiling key value with what's given and
395 * returns the value that was swapped.
396 *
397 * @param[in] keyValue - New ceiling key value
398 *
399 * @return - Ceiling key value prior to swapping
400 */
401 inline auto swapCeilingKeyValue(int64_t keyValue)
402 {
403 std::swap(_ceilingKeyValue, keyValue);
404 return keyValue;
405 };
406
Matthew Barth24623522017-06-21 14:09:57 -0500407 /**
408 * @brief Get the increase speed delta
409 *
410 * @return - The current increase speed delta
411 */
412 inline auto& getIncSpeedDelta() const
413 {
414 return _incSpeedDelta;
415 };
416
Matthew Barth240397b2017-06-22 11:23:30 -0500417 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500418 * @brief Get the decrease speed delta
419 *
420 * @return - The current decrease speed delta
421 */
422 inline auto& getDecSpeedDelta() const
423 {
424 return _decSpeedDelta;
425 };
426
427 /**
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500428 * @brief Set the floor speed to the given speed and increase target
Matthew Barth98726c42017-10-17 10:35:20 -0500429 * speed to the floor when target is below floor where floor changes
430 * are allowed.
Matthew Barthb4a7cb92017-06-28 15:29:50 -0500431 *
432 * @param[in] speed - Speed to set the floor to
433 */
434 void setFloor(uint64_t speed);
435
436 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500437 * @brief Set the requested speed base to be used as the speed to
438 * base a new requested speed target from
439 *
440 * @param[in] speedBase - Base speed value to use
441 */
442 inline void setRequestSpeedBase(uint64_t speedBase)
443 {
444 _requestSpeedBase = speedBase;
445 };
446
447 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500448 * @brief Calculate the requested target speed from the given delta
449 * and increase the fan speeds, not going above the ceiling.
450 *
451 * @param[in] targetDelta - The delta to increase the target speed by
452 */
453 void requestSpeedIncrease(uint64_t targetDelta);
454
Matthew Barth0ce99d82017-06-22 15:07:29 -0500455 /**
456 * @brief Calculate the requested target speed from the given delta
457 * and increase the fan speeds, not going above the ceiling.
458 *
459 * @param[in] targetDelta - The delta to increase the target speed by
460 */
461 void requestSpeedDecrease(uint64_t targetDelta);
462
Matthew Barth8600d9a2017-06-23 14:38:05 -0500463 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500464 * @brief Callback function for the increase timer that delays
465 * processing of requested speed increases while fans are increasing
466 */
467 void incTimerExpired();
468
469 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500470 * @brief Callback function for the decrease timer that processes any
471 * requested speed decreases if allowed
472 */
473 void decTimerExpired();
474
Matthew Barth90149802017-08-15 10:51:37 -0500475 /**
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700476 * @brief Get the event loop used with this zone's timers
Matthew Barthbfb1a562017-10-05 17:03:40 -0500477 *
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700478 * @return - The event loop for timers
Matthew Barthbfb1a562017-10-05 17:03:40 -0500479 */
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700480 inline auto& getEventLoop()
Matthew Barthbfb1a562017-10-05 17:03:40 -0500481 {
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700482 return _eventLoop;
Matthew Barthbfb1a562017-10-05 17:03:40 -0500483 }
484
485 /**
Matthew Barth33bfe762018-11-05 11:13:25 -0600486 * @brief Remove the given signal event
487 *
488 * @param[in] seIter - Iterator pointing to the signal event to remove
489 */
490 inline void removeSignal(std::vector<SignalEvent>::iterator& seIter)
491 {
Matthew Barth33bfe762018-11-05 11:13:25 -0600492 std::get<signalEventDataPos>(*seIter).reset();
493 if (std::get<signalMatchPos>(*seIter) != nullptr)
494 {
495 std::get<signalMatchPos>(*seIter).reset();
496 }
Matthew Barth33bfe762018-11-05 11:13:25 -0600497 }
498
499 /**
Matthew Barthbfb1a562017-10-05 17:03:40 -0500500 * @brief Get the list of timer events
501 *
502 * @return - List of timer events
503 */
504 inline auto& getTimerEvents()
505 {
506 return _timerEvents;
507 }
508
509 /**
510 * @brief Find the first instance of a timer event
511 *
512 * @param[in] eventGroup - Group associated with a timer
513 * @param[in] eventActions - List of actions associated with a timer
Matthew Barthd7b716a2018-11-16 13:37:57 -0600514 * @param[in] eventTimers - List of timers to find the timer in
Matthew Barthbfb1a562017-10-05 17:03:40 -0500515 *
516 * @return - Iterator to the timer event
517 */
518 std::vector<TimerEvent>::iterator findTimer(
519 const Group& eventGroup,
Matthew Barthd7b716a2018-11-16 13:37:57 -0600520 const std::vector<Action>& eventActions,
521 std::vector<TimerEvent>& eventTimers);
Matthew Barthbfb1a562017-10-05 17:03:40 -0500522
523 /**
524 * @brief Add a timer to the list of timer based events
525 *
Matthew Barthd7b716a2018-11-16 13:37:57 -0600526 * @param[in] name - Event name associated with timer
William A. Kennington III94fe1a02018-10-30 19:00:27 -0700527 * @param[in] group - Group associated with a timer
528 * @param[in] actions - List of actions associated with a timer
529 * @param[in] tConf - Configuration for the new timer
Matthew Barthbfb1a562017-10-05 17:03:40 -0500530 */
Matthew Barthd7b716a2018-11-16 13:37:57 -0600531 void addTimer(const std::string& name,
532 const Group& group,
William A. Kennington III94fe1a02018-10-30 19:00:27 -0700533 const std::vector<Action>& actions,
534 const TimerConf& tConf);
Matthew Barthbfb1a562017-10-05 17:03:40 -0500535
536 /**
Matthew Barth90149802017-08-15 10:51:37 -0500537 * @brief Callback function for event timers that processes the given
Matthew Barthf9201ab2017-09-11 16:07:58 -0500538 * actions for a group
Matthew Barth90149802017-08-15 10:51:37 -0500539 *
Matthew Barthf9201ab2017-09-11 16:07:58 -0500540 * @param[in] eventGroup - Group to process actions on
541 * @param[in] eventActions - List of event actions to run
Matthew Barth90149802017-08-15 10:51:37 -0500542 */
William A. Kennington IIIc0c5f072018-10-30 19:11:01 -0700543 void timerExpired(const Group& eventGroup,
544 const std::vector<Action>& eventActions);
Matthew Barth90149802017-08-15 10:51:37 -0500545
Matthew Bartha603ed02018-01-19 16:56:26 -0600546 /**
547 * @brief Get the service for a given path and interface from cached
548 * dataset and add a service that's not found
549 *
550 * @param[in] path - Path to get service for
551 * @param[in] intf - Interface to get service for
552 *
553 * @return - The service name
554 */
555 const std::string& getService(const std::string& path,
556 const std::string& intf);
557
558 /**
559 * @brief Add a set of services for a path and interface
560 * by retrieving all the path subtrees to the given depth
561 * from root for the interface
562 *
563 * @param[in] path - Path to add services for
564 * @param[in] intf - Interface to add services for
565 * @param[in] depth - Depth of tree traversal from root path
566 *
567 * @return - The associated service to the given path and interface
568 * or empty string for no service found
569 */
570 const std::string& addServices(const std::string& path,
571 const std::string& intf,
572 int32_t depth);
573
Matthew Barth6faf8942019-01-22 09:26:09 -0600574 /**
Matthew Barth016bd242018-03-07 16:06:06 -0600575 * @brief Dbus signal change callback handler
576 *
577 * @param[in] msg - Expanded sdbusplus message data
578 * @param[in] eventData - The single event's data
579 */
580 void handleEvent(sdbusplus::message::message& msg,
581 const EventData* eventData);
582
583 /**
584 * @brief Add a signal to the list of signal based events
585 *
Matthew Barth79cb8312018-11-14 15:20:31 -0600586 * @param[in] name - Event name
Matthew Barth016bd242018-03-07 16:06:06 -0600587 * @param[in] data - Event data for signal
588 * @param[in] match - Subscribed signal match
589 */
590 inline void addSignal(
Matthew Barth79cb8312018-11-14 15:20:31 -0600591 const std::string& name,
Matthew Barth016bd242018-03-07 16:06:06 -0600592 std::unique_ptr<EventData>&& data,
593 std::unique_ptr<sdbusplus::server::match::match>&& match)
594 {
Matthew Barth79cb8312018-11-14 15:20:31 -0600595 _signalEvents[name].emplace_back(std::move(data), std::move(match));
Matthew Barth016bd242018-03-07 16:06:06 -0600596 }
597
598 /**
Matthew Barth70b2e7d2019-02-18 11:03:07 -0600599 * @brief Set a property to be persisted
600 *
601 * @param[in] intf - Interface containing property
602 * @param[in] prop - Property to be persisted
603 */
604 inline void setPersisted(const std::string& intf,
605 const std::string& prop)
606 {
607 _persisted[intf].emplace_back(prop);
608 }
609
610 /**
611 * @brief Get persisted property
612 *
613 * @param[in] intf - Interface containing property
614 * @param[in] prop - Property persisted
615 *
616 * @return - True if property is to be persisted, false otherwise
617 */
618 auto getPersisted(const std::string& intf,
619 const std::string& prop);
620
621 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600622 * @brief Get a property value from the zone object or the bus when
623 * the property requested is not on the zone object
624 *
625 * @param[in] path - Path of object
626 * @param[in] intf - Object interface
627 * @param[in] prop - Object property
628 *
629 * @return - Property's value
630 */
631 template <typename T>
632 auto getPropertyByName(const std::string& path,
633 const std::string& intf,
634 const std::string& prop)
635 {
636 T value;
637 auto pathIter = _objects.find(path);
638 if (pathIter != _objects.end())
639 {
640 auto intfIter = pathIter->second.find(intf);
641 if (intfIter != pathIter->second.end())
642 {
643 if (intf == "xyz.openbmc_project.Control.ThermalMode")
644 {
645 auto var = ThermalMode::getPropertyByName(prop);
646 // Use visitor to determine if requested property
647 // type(T) is available on this interface and read it
648 std::visit([&value](auto&& val)
649 {
650 using V = std::decay_t<decltype(val)>;
651 if constexpr(std::is_same_v<T, V>)
652 {
653 value = val;
654 }
655 }, var);
656
657 return value;
658 }
659 }
660 }
661
Matthew Barth7f4c5482020-02-07 16:14:46 -0600662 // Retrieve the property's value applying any visitors necessary
Matthew Barth766f8542019-01-29 12:44:13 -0600663 auto service = getService(path, intf);
Matthew Barth7f4c5482020-02-07 16:14:46 -0600664 auto variant =
665 util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
666 _bus, service, path, intf, prop);
667 value = getPropertyValueVisitor<T>(
668 intf.c_str(), prop.c_str(), variant);
Matthew Barth766f8542019-01-29 12:44:13 -0600669
670 return value;
671 };
672
673 /**
Matthew Barth6faf8942019-01-22 09:26:09 -0600674 * @brief Overridden thermal object's set 'Current' property function
675 *
676 * @param[in] value - Value to set 'Current' to
677 *
678 * @return - The updated value of the 'Current' property
679 */
680 virtual std::string current(std::string value);
681
Matt Spinler7f88fe62017-04-10 14:39:02 -0500682 private:
683
684 /**
685 * The dbus object
686 */
687 sdbusplus::bus::bus& _bus;
688
689 /**
Matthew Barth93af4192019-01-18 09:30:57 -0600690 * Zone object path
691 */
692 const std::string _path;
693
694 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600695 * Zone supported interfaces
696 */
697 const std::vector<std::string> _ifaces;
698
699 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500700 * Full speed for the zone
701 */
702 const uint64_t _fullSpeed;
703
704 /**
705 * The zone number
706 */
707 const size_t _zoneNum;
708
709 /**
Matthew Barth1de66622017-06-12 13:13:02 -0500710 * The default floor speed for the zone
711 */
Matthew Barth8d06a832019-10-02 14:43:39 -0500712 uint64_t _defFloorSpeed;
Matthew Barth1de66622017-06-12 13:13:02 -0500713
714 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500715 * The default ceiling speed for the zone
716 */
717 const uint64_t _defCeilingSpeed;
718
719 /**
Matthew Barth4af419c2017-06-12 13:39:31 -0500720 * The floor speed to not go below
721 */
722 uint64_t _floorSpeed = _defFloorSpeed;
723
724 /**
Matthew Barthe0ca13e2017-06-13 16:29:09 -0500725 * The ceiling speed to not go above
726 */
727 uint64_t _ceilingSpeed = _defCeilingSpeed;
728
729 /**
730 * The previous sensor value for calculating the ceiling
731 */
732 int64_t _ceilingKeyValue = 0;
733
734 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500735 * Automatic fan control active state
736 */
737 bool _isActive = true;
738
739 /**
Matthew Barth240397b2017-06-22 11:23:30 -0500740 * Target speed for this zone
741 */
742 uint64_t _targetSpeed = _fullSpeed;
743
744 /**
Matthew Barth24623522017-06-21 14:09:57 -0500745 * Speed increase delta
746 */
747 uint64_t _incSpeedDelta = 0;
748
749 /**
Matthew Barth0ce99d82017-06-22 15:07:29 -0500750 * Speed decrease delta
751 */
752 uint64_t _decSpeedDelta = 0;
753
754 /**
Matthew Barth1bfdc422017-09-14 16:23:28 -0500755 * Requested speed base
756 */
757 uint64_t _requestSpeedBase = 0;
758
759 /**
Matthew Bartha9561842017-06-29 11:43:45 -0500760 * Speed increase delay in seconds
761 */
762 std::chrono::seconds _incDelay;
763
764 /**
765 * Speed decrease interval in seconds
766 */
767 std::chrono::seconds _decInterval;
768
769 /**
Matthew Barth1ee48f22017-06-27 15:14:48 -0500770 * The increase timer object
771 */
William A. Kennington III8fd879f2018-10-30 19:49:29 -0700772 Timer _incTimer;
Matthew Barth1ee48f22017-06-27 15:14:48 -0500773
774 /**
Matthew Barth8600d9a2017-06-23 14:38:05 -0500775 * The decrease timer object
776 */
William A. Kennington III8fd879f2018-10-30 19:49:29 -0700777 Timer _decTimer;
Matthew Barth8600d9a2017-06-23 14:38:05 -0500778
779 /**
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700780 * Event loop used on set speed event timers
Matthew Barth90149802017-08-15 10:51:37 -0500781 */
William A. Kennington III1cfc2f12018-10-19 17:29:46 -0700782 sdeventplus::Event _eventLoop;
Matthew Barth90149802017-08-15 10:51:37 -0500783
784 /**
Matt Spinler7f88fe62017-04-10 14:39:02 -0500785 * The vector of fans in this zone
786 */
787 std::vector<std::unique_ptr<Fan>> _fans;
Matthew Barth38a93a82017-05-11 14:12:27 -0500788
789 /**
790 * @brief Map of object property values
791 */
Matthew Barthcec5ab72017-06-02 15:20:56 -0500792 std::map<std::string,
793 std::map<std::string,
794 std::map<std::string,
Matthew Barth9e741ed2017-06-02 16:29:09 -0500795 PropertyVariantType>>> _properties;
Matthew Barth38a93a82017-05-11 14:12:27 -0500796
797 /**
Matthew Barth766f8542019-01-29 12:44:13 -0600798 * @brief Map of zone objects
799 */
800 std::map<std::string,
801 std::map<std::string,
802 std::map<std::string,
803 EventData*>>> _objects;
804
805 /**
Matthew Barth70b2e7d2019-02-18 11:03:07 -0600806 * @brief Map of interfaces to persisted properties
807 */
808 std::map<std::string, std::vector<std::string>> _persisted;
809
810 /**
Matthew Barth861d77c2017-05-22 14:18:25 -0500811 * @brief Map of active fan control allowed by groups
812 */
Matthew Barth60b00762017-08-15 13:39:06 -0500813 std::map<const Group, bool> _active;
Matthew Barth861d77c2017-05-22 14:18:25 -0500814
815 /**
Matthew Barth98726c42017-10-17 10:35:20 -0500816 * @brief Map of floor change allowed by groups
817 */
818 std::map<const Group, bool> _floorChange;
819
820 /**
Matthew Barthe4338cd2017-12-14 11:14:30 -0600821 * @brief Map of groups controlling decreases allowed
822 */
823 std::map<const Group, bool> _decAllowed;
824
825 /**
Matthew Barthe59fdf72017-09-27 09:33:42 -0500826 * @brief Map of group service names
827 */
828 std::map<const Group, std::vector<Service>> _services;
829
830 /**
Matthew Bartha603ed02018-01-19 16:56:26 -0600831 * @brief Map tree of paths to services of interfaces
832 */
833 std::map<std::string,
834 std::map<std::string,
835 std::vector<std::string>>> _servTree;
836
837 /**
Matthew Barth79cb8312018-11-14 15:20:31 -0600838 * @brief List of signal event arguments and Dbus matches
839 * for callbacks per event name
Matthew Barth38a93a82017-05-11 14:12:27 -0500840 */
Matthew Barth79cb8312018-11-14 15:20:31 -0600841 std::map<std::string, std::vector<SignalEvent>> _signalEvents;
Matthew Barth38a93a82017-05-11 14:12:27 -0500842
843 /**
Matthew Barthd7b716a2018-11-16 13:37:57 -0600844 * @brief List of timers per event name
Matthew Barth90149802017-08-15 10:51:37 -0500845 */
Matthew Barthd7b716a2018-11-16 13:37:57 -0600846 std::map<std::string, std::vector<TimerEvent>> _timerEvents;
Matthew Barth90149802017-08-15 10:51:37 -0500847
848 /**
Matthew Barthcc8912e2019-01-21 11:35:27 -0600849 * @brief Save the thermal control current mode property
850 * to persisted storage
851 */
852 void saveCurrentMode();
853
854 /**
Matthew Barth9e4db252019-01-21 13:08:02 -0600855 * @brief Restore persisted thermal control current mode property
856 * value, setting the mode to "Default" otherwise
857 */
858 void restoreCurrentMode();
859
860 /**
Matthew Barth4e728542017-09-14 16:47:55 -0500861 * @brief Get the request speed base if defined, otherwise the
862 * the current target speed is returned
863 *
864 * @return - The request speed base or current target speed
865 */
866 inline auto getRequestSpeedBase() const
867 {
868 return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
869 };
Matt Spinler7f88fe62017-04-10 14:39:02 -0500870};
871
872}
873}
874}