1 #pragma once
2 #include <chrono>
3 #include <vector>
4 #include <algorithm>
5 #include <sdbusplus/bus.hpp>
6 #include "fan.hpp"
7 #include "types.hpp"
8 #include "timer.hpp"
9 
10 namespace phosphor
11 {
12 namespace fan
13 {
14 namespace control
15 {
16 
17 /**
18  * The mode fan control will run in:
19  *   - init - only do the initialization steps
20  *   - control - run normal control algorithms
21  */
22 enum class Mode
23 {
24     init,
25     control
26 };
27 
28 /**
29  * @class Represents a fan control zone, which is a group of fans
30  * that behave the same.
31  */
32 class Zone
33 {
34     public:
35 
36         Zone() = delete;
37         Zone(const Zone&) = delete;
38         Zone(Zone&&) = default;
39         Zone& operator=(const Zone&) = delete;
40         Zone& operator=(Zone&&) = delete;
41         ~Zone() = default;
42 
43         /**
44          * Constructor
45          * Creates the appropriate fan objects based on
46          * the zone definition data passed in.
47          *
48          * @param[in] mode - mode of fan control
49          * @param[in] bus - the dbus object
50          * @param[in] events - sd_event pointer
51          * @param[in] def - the fan zone definition data
52          */
53         Zone(Mode mode,
54              sdbusplus::bus::bus& bus,
55              phosphor::fan::event::EventPtr& events,
56              const ZoneDefinition& def);
57 
58         /**
59          * Sets all fans in the zone to the speed
60          * passed in when the zone is active
61          *
62          * @param[in] speed - the fan speed
63          */
64         void setSpeed(uint64_t speed);
65 
66         /**
67          * Sets the zone to full speed regardless of zone's active state
68          */
69         void setFullSpeed();
70 
71         /**
72          * @brief Sets the automatic fan control allowed active state
73          *
74          * @param[in] group - A group that affects the active state
75          * @param[in] isActiveAllow - Active state according to group
76          */
77         void setActiveAllow(const Group* group, bool isActiveAllow);
78 
79         /**
80          * @brief Sets a given object's property value
81          *
82          * @param[in] object - Name of the object containing the property
83          * @param[in] interface - Interface name containing the property
84          * @param[in] property - Property name
85          * @param[in] value - Property value
86          */
87         template <typename T>
88         void setPropertyValue(const char* object,
89                               const char* interface,
90                               const char* property,
91                               T value)
92         {
93             _properties[object][interface][property] = value;
94         };
95 
96         /**
97          * @brief Get the value of an object's property
98          *
99          * @param[in] object - Name of the object containing the property
100          * @param[in] interface - Interface name containing the property
101          * @param[in] property - Property name
102          *
103          * @return - The property value
104          */
105         template <typename T>
106         inline auto getPropertyValue(const std::string& object,
107                                      const std::string& interface,
108                                      const std::string& property)
109         {
110             return sdbusplus::message::variant_ns::get<T>(
111                     _properties.at(object).at(interface).at(property));
112         };
113 
114         /**
115          * @brief Get the object's property variant
116          *
117          * @param[in] object - Name of the object containing the property
118          * @param[in] interface - Interface name containing the property
119          * @param[in] property - Property name
120          *
121          * @return - The property variant
122          */
123         inline auto getPropValueVariant(const std::string& object,
124                                         const std::string& interface,
125                                         const std::string& property)
126         {
127             return _properties.at(object).at(interface).at(property);
128         };
129 
130         /**
131          * @brief Initialize a set speed event properties and actions
132          *
133          * @param[in] event - Set speed event
134          */
135         void initEvent(const SetSpeedEvent& event);
136 
137         /**
138          * @brief Removes all the set speed event properties and actions
139          *
140          * @param[in] event - Set speed event
141          */
142         void removeEvent(const SetSpeedEvent& event);
143 
144         /**
145          * @brief Get the default floor speed
146          *
147          * @return - The defined default floor speed
148          */
149         inline auto getDefFloor()
150         {
151             return _defFloorSpeed;
152         };
153 
154         /**
155          * @brief Get the ceiling speed
156          *
157          * @return - The current ceiling speed
158          */
159         inline auto& getCeiling() const
160         {
161             return _ceilingSpeed;
162         };
163 
164         /**
165          * @brief Set the ceiling speed to the given speed
166          *
167          * @param[in] speed - Speed to set the ceiling to
168          */
169         inline void setCeiling(uint64_t speed)
170         {
171             _ceilingSpeed = speed;
172         };
173 
174         /**
175          * @brief Swaps the ceiling key value with what's given and
176          * returns the value that was swapped.
177          *
178          * @param[in] keyValue - New ceiling key value
179          *
180          * @return - Ceiling key value prior to swapping
181          */
182         inline auto swapCeilingKeyValue(int64_t keyValue)
183         {
184             std::swap(_ceilingKeyValue, keyValue);
185             return keyValue;
186         };
187 
188         /**
189          * @brief Get the increase speed delta
190          *
191          * @return - The current increase speed delta
192          */
193         inline auto& getIncSpeedDelta() const
194         {
195             return _incSpeedDelta;
196         };
197 
198         /**
199          * @brief Get the decrease speed delta
200          *
201          * @return - The current decrease speed delta
202          */
203         inline auto& getDecSpeedDelta() const
204         {
205             return _decSpeedDelta;
206         };
207 
208         /**
209          * @brief Set the floor speed to the given speed and increase target
210          * speed to the floor when target is below floor.
211          *
212          * @param[in] speed - Speed to set the floor to
213          */
214         void setFloor(uint64_t speed);
215 
216         /**
217          * @brief Set the requested speed base to be used as the speed to
218          * base a new requested speed target from
219          *
220          * @param[in] speedBase - Base speed value to use
221          */
222         inline void setRequestSpeedBase(uint64_t speedBase)
223         {
224             _requestSpeedBase = speedBase;
225         };
226 
227         /**
228          * @brief Calculate the requested target speed from the given delta
229          * and increase the fan speeds, not going above the ceiling.
230          *
231          * @param[in] targetDelta - The delta to increase the target speed by
232          */
233         void requestSpeedIncrease(uint64_t targetDelta);
234 
235         /**
236          * @brief Calculate the requested target speed from the given delta
237          * and increase the fan speeds, not going above the ceiling.
238          *
239          * @param[in] targetDelta - The delta to increase the target speed by
240          */
241         void requestSpeedDecrease(uint64_t targetDelta);
242 
243         /**
244          * @brief Callback function for the increase timer that delays
245          * processing of requested speed increases while fans are increasing
246          */
247         void incTimerExpired();
248 
249         /**
250          * @brief Callback function for the decrease timer that processes any
251          * requested speed decreases if allowed
252          */
253         void decTimerExpired();
254 
255         /**
256          * @brief Callback function for event timers that processes the given
257          * actions for a group
258          *
259          * @param[in] eventGroup - Group to process actions on
260          * @param[in] eventActions - List of event actions to run
261          */
262         void timerExpired(Group eventGroup, std::vector<Action> eventActions);
263 
264     private:
265 
266         /**
267          * The dbus object
268          */
269         sdbusplus::bus::bus& _bus;
270 
271         /**
272          * Full speed for the zone
273          */
274         const uint64_t _fullSpeed;
275 
276         /**
277          * The zone number
278          */
279         const size_t _zoneNum;
280 
281         /**
282          * The default floor speed for the zone
283          */
284         const uint64_t _defFloorSpeed;
285 
286         /**
287          * The default ceiling speed for the zone
288          */
289         const uint64_t _defCeilingSpeed;
290 
291         /**
292          * The floor speed to not go below
293          */
294         uint64_t _floorSpeed = _defFloorSpeed;
295 
296         /**
297          * The ceiling speed to not go above
298          */
299         uint64_t _ceilingSpeed = _defCeilingSpeed;
300 
301         /**
302          * The previous sensor value for calculating the ceiling
303          */
304         int64_t _ceilingKeyValue = 0;
305 
306         /**
307          * Automatic fan control active state
308          */
309         bool _isActive = true;
310 
311         /**
312          * Target speed for this zone
313          */
314         uint64_t _targetSpeed = _fullSpeed;
315 
316         /**
317          * Speed increase delta
318          */
319         uint64_t _incSpeedDelta = 0;
320 
321         /**
322          * Speed decrease delta
323          */
324         uint64_t _decSpeedDelta = 0;
325 
326         /**
327          * Requested speed base
328          */
329         uint64_t _requestSpeedBase = 0;
330 
331         /**
332          * Speed increase delay in seconds
333          */
334         std::chrono::seconds _incDelay;
335 
336         /**
337          * Speed decrease interval in seconds
338          */
339         std::chrono::seconds _decInterval;
340 
341         /**
342          * The increase timer object
343          */
344         phosphor::fan::util::Timer _incTimer;
345 
346         /**
347          * The decrease timer object
348          */
349         phosphor::fan::util::Timer _decTimer;
350 
351         /**
352          * Dbus event used on set speed event timers
353          */
354         phosphor::fan::event::EventPtr& _sdEvents;
355 
356         /**
357          * The vector of fans in this zone
358          */
359         std::vector<std::unique_ptr<Fan>> _fans;
360 
361         /**
362          * @brief Map of object property values
363          */
364         std::map<std::string,
365                  std::map<std::string,
366                           std::map<std::string,
367                                    PropertyVariantType>>> _properties;
368 
369         /**
370          * @brief Map of active fan control allowed by groups
371          */
372         std::map<const Group, bool> _active;
373 
374         /**
375          * @brief List of signal event arguments and Dbus matches for callbacks
376          */
377         std::vector<SignalEvent> _signalEvents;
378 
379         /**
380          * @brief List of timers for events
381          */
382         std::vector<std::unique_ptr<phosphor::fan::util::Timer>> _timerEvents;
383 
384         /**
385          * @brief Get the request speed base if defined, otherwise the
386          * the current target speed is returned
387          *
388          * @return - The request speed base or current target speed
389          */
390         inline auto getRequestSpeedBase() const
391         {
392             return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
393         };
394 
395         /**
396          * @brief Refresh the given property's cached value
397          *
398          * @param[in] bus - the bus to use
399          * @param[in] path - the dbus path name
400          * @param[in] iface - the dbus interface name
401          * @param[in] prop - the property name
402          */
403         void refreshProperty(sdbusplus::bus::bus& bus,
404                              const std::string& path,
405                              const std::string& iface,
406                              const std::string& prop);
407 
408         /**
409          * @brief Get a property value from the path/interface given
410          *
411          * @param[in] bus - the bus to use
412          * @param[in] path - the dbus path name
413          * @param[in] iface - the dbus interface name
414          * @param[in] prop - the property name
415          * @param[out] value - the value of the property
416          */
417         static void getProperty(sdbusplus::bus::bus& bus,
418                                 const std::string& path,
419                                 const std::string& iface,
420                                 const std::string& prop,
421                                 PropertyVariantType& value);
422 
423         /**
424          * @brief Dbus signal change callback handler
425          *
426          * @param[in] msg - Expanded sdbusplus message data
427          * @param[in] eventData - The single event's data
428          */
429         void handleEvent(sdbusplus::message::message& msg,
430                          const EventData* eventData);
431 };
432 
433 }
434 }
435 }
436