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