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