1 #pragma once
2 
3 #include <sdbusplus/bus.hpp>
4 #include <tuple>
5 #include <vector>
6 #include "tach_sensor.hpp"
7 #include "types.hpp"
8 
9 namespace phosphor
10 {
11 namespace fan
12 {
13 namespace monitor
14 {
15 
16 
17 /**
18  * @class Fan
19  *
20  * Represents a fan, which can contain 1 or more sensors which
21  * loosely correspond to rotors.  See below.
22  *
23  * There is a sensor when hwmon exposes one, which means there is a
24  * speed value to be read.  Sometimes there is a sensor per rotor,
25  * and other times multiple rotors just use 1 sensor total where
26  * the sensor reports the slowest speed of all of the rotors.
27  *
28  * A rotor's speed is set by writing the Target value of a sensor.
29  * Sometimes each sensor in a fan supports having a Target, and other
30  * times not all of them do.  A TachSensor object knows if it supports
31  * the Target property.
32  *
33  * The strategy for monitoring fan speeds is as follows:
34  *
35  * Every time a Target (new speed written) or Input (actual speed read)
36  * sensor changes, check if the input value is within some range of the target
37  * value.  If it isn't, start a timer at the end of which the sensor will be
38  * set to not functional.  If enough sensors in the fan are now nonfunctional,
39  * set the whole fan to nonfunctional in the inventory.
40  *
41  * When sensor inputs come back within a specified range of the target,
42  * stop its timer if running, make the sensor functional again if it wasn't,
43  * and if enough sensors in the fan are now functional set the whole fan
44  * back to functional in the inventory.
45  */
46 class Fan
47 {
48     using Property = std::string;
49     using Value = sdbusplus::message::variant<bool>;
50     using PropertyMap = std::map<Property, Value>;
51 
52     using Interface = std::string;
53     using InterfaceMap = std::map<Interface, PropertyMap>;
54 
55     using Object = sdbusplus::message::object_path;
56     using ObjectMap = std::map<Object, InterfaceMap>;
57 
58     public:
59 
60         Fan() = delete;
61         Fan(const Fan&) = delete;
62         Fan(Fan&&) = default;
63         Fan& operator=(const Fan&) = delete;
64         Fan& operator=(Fan&&) = default;
65         ~Fan() = default;
66 
67         /**
68          * @brief Constructor
69          *
70          * @param bus - the dbus object
71          * @param events - pointer to sd_event object
72          * @param def - the fan definition structure
73          */
74         Fan(sdbusplus::bus::bus& bus,
75             std::shared_ptr<sd_event>& events,
76             const FanDefinition& def);
77 
78         /**
79          * @brief Callback function for when an input sensor changes
80          *
81          * Starts a timer, where if it expires then the sensor
82          * was out of range for too long and can be considered not functional.
83          */
84         void tachChanged(TachSensor& sensor);
85 
86         /**
87          * @brief Calls tachChanged(sensor) on each sensor
88          */
89         void tachChanged();
90 
91         /**
92          * @brief The callback function for the timer
93          *
94          * Sets the sensor to not functional.
95          * If enough sensors are now not functional,
96          * updates the functional status of the whole
97          * fan in the inventory.
98          *
99          * @param[in] sensor - the sensor whose timer expired
100          */
101         void timerExpired(TachSensor& sensor);
102 
103     private:
104 
105         /**
106          * @brief Returns the target speed of the sensor
107          *
108          * If the sensor itself doesn't have a target, it finds
109          * the target speed from another sensor.
110          *
111          * @param[in] sensor - the sensor to get the target speed for
112          */
113         uint64_t getTargetSpeed(const TachSensor& sensor);
114 
115         /**
116          * @brief Returns true if the sensor input is not within
117          * some deviation of the target.
118          *
119          * @param[in] sensor - the sensor to check
120          */
121         bool outOfRange(const TachSensor& sensor);
122 
123         /**
124          * @brief Returns true if too many sensors are nonfunctional
125          *        as defined by _numSensorFailsForNonFunc
126          */
127         bool tooManySensorsNonfunctional();
128 
129         /**
130          * @brief Updates the Functional property in the inventory
131          *        for the fan based on the value passed in.
132          *
133          * @param[in] functional - If the Functional property should
134          *                         be set to true or false.
135          */
136         void updateInventory(bool functional);
137 
138         /**
139          * @brief Returns the object map to use when updating the inventory
140          *
141          * @param[in] functional - If the Functional property should
142          *                         be set to true or false.
143          */
144         ObjectMap getObjectMap(bool functional);
145 
146         /**
147          * @brief the dbus object
148          */
149         sdbusplus::bus::bus& _bus;
150 
151         /**
152          * @brief The inventory name of the fan
153          */
154         const std::string _name;
155 
156         /**
157          * @brief The percentage that the input speed must be below
158          *        the target speed to be considered an error.
159          *        Between 0 and 100.
160          */
161         const size_t _deviation;
162 
163         /**
164          * The number of sensors that must be nonfunctional at the
165          * same time in order for the fan to be set to nonfunctional
166          * in the inventory.
167          */
168         const size_t _numSensorFailsForNonFunc;
169 
170         /**
171          * @brief The current functional state of the fan
172          */
173         bool _functional = true;
174 
175         /**
176          * The sensor objects for the fan
177          */
178         std::vector<std::unique_ptr<TachSensor>> _sensors;
179 };
180 
181 }
182 }
183 }
184