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