xref: /openbmc/phosphor-fan-presence/monitor/tach_sensor.hpp (revision 9e9f599cece7fe6cdf99b1927a515fc8a552b7e9)
1 #pragma once
2 
3 #include <sdbusplus/bus.hpp>
4 #include <sdbusplus/server.hpp>
5 #include <sdeventplus/clock.hpp>
6 #include <sdeventplus/event.hpp>
7 #include <sdeventplus/utility/timer.hpp>
8 
9 #include <chrono>
10 
11 namespace phosphor
12 {
13 namespace fan
14 {
15 namespace monitor
16 {
17 
18 class Fan;
19 
20 constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/";
21 
22 /**
23  * The mode fan monitor will run in:
24  *   - init - only do the initialization steps
25  *   - monitor - run normal monitoring algorithm
26  */
27 enum class Mode
28 {
29     init,
30     monitor
31 };
32 
33 /**
34  * The mode that the timer is running in:
35  *   - func - Transition to functional state timer
36  *   - nonfunc - Transition to nonfunctional state timer
37  */
38 enum class TimerMode
39 {
40     func,
41     nonfunc
42 };
43 
44 /**
45  * @class TachSensor
46  *
47  * This class represents the sensor that reads a tach value.
48  * It may also support a Target, which is the property used to
49  * set a speed.  Since it doesn't necessarily have a Target, it
50  * won't for sure know if it is running too slow, so it leaves
51  * that determination to other code.
52  *
53  * This class has a parent Fan object that knows about all
54  * sensors for that fan.
55  */
56 class TachSensor
57 {
58   public:
59     TachSensor() = delete;
60     TachSensor(const TachSensor&) = delete;
61     // TachSensor is not moveable since the this pointer is used as systemd
62     // callback context.
63     TachSensor(TachSensor&&) = delete;
64     TachSensor& operator=(const TachSensor&) = delete;
65     TachSensor& operator=(TachSensor&&) = delete;
66     ~TachSensor() = default;
67 
68     /**
69      * @brief Constructor
70      *
71      * @param[in] mode - mode of fan monitor
72      * @param[in] bus - the dbus object
73      * @param[in] fan - the parent fan object
74      * @param[in] id - the id of the sensor
75      * @param[in] hasTarget - if the sensor supports
76      *                        setting the speed
77      * @param[in] funcDelay - Delay to mark functional
78      * @param[in] interface - the interface of the target
79      * @param[in] factor - the factor of the sensor target
80      * @param[in] offset - the offset of the sensor target
81      * @param[in] timeout - Normal timeout value to use
82      * @param[in] event - Event loop reference
83      */
84     TachSensor(Mode mode, sdbusplus::bus::bus& bus, Fan& fan,
85                const std::string& id, bool hasTarget, size_t funcDelay,
86                const std::string& interface, double factor, int64_t offset,
87                size_t timeout, const sdeventplus::Event& event);
88 
89     /**
90      * @brief Returns the target speed value
91      */
92     uint64_t getTarget() const;
93 
94     /**
95      * @brief Returns the input speed value
96      */
97     inline double getInput() const
98     {
99         return _tachInput;
100     }
101 
102     /**
103      * @brief Returns true if sensor has a target
104      */
105     inline bool hasTarget() const
106     {
107         return _hasTarget;
108     }
109 
110     /**
111      * @brief Returns the interface of the sensor target
112      */
113     inline std::string getInterface() const
114     {
115         return _interface;
116     }
117 
118     /**
119      * @brief Returns the factor of the sensor target
120      */
121     inline double getFactor() const
122     {
123         return _factor;
124     }
125 
126     /**
127      * @brief Returns the offset of the sensor target
128      */
129     inline int64_t getOffset() const
130     {
131         return _offset;
132     }
133 
134     /**
135      * Returns true if the hardware behind this
136      * sensor is considered working OK/functional.
137      */
138     inline bool functional() const
139     {
140         return _functional;
141     }
142 
143     /**
144      * Set the functional status and update inventory to match
145      */
146     void setFunctional(bool functional);
147 
148     /**
149      * @brief Says if the timer is running or not
150      *
151      * @return bool - if timer is currently running
152      */
153     inline bool timerRunning()
154     {
155         return _timer.isEnabled();
156     }
157 
158     /**
159      * @brief Stops the timer when the given mode differs and starts
160      * the associated timer for the mode given if not already running
161      *
162      * @param[in] mode - mode of timer to start
163      */
164     void startTimer(TimerMode mode);
165 
166     /**
167      * @brief Stops the timer
168      */
169     inline void stopTimer()
170     {
171         _timer.setEnabled(false);
172     }
173 
174     /**
175      * @brief Return the given timer mode's delay time
176      *
177      * @param[in] mode - mode of timer to get delay time for
178      */
179     std::chrono::microseconds getDelay(TimerMode mode);
180 
181     /**
182      * Returns the sensor name
183      */
184     inline const std::string& name() const
185     {
186         return _name;
187     };
188 
189   private:
190     /**
191      * @brief Returns the match string to use for matching
192      *        on a properties changed signal.
193      */
194     std::string getMatchString(const std::string& interface);
195 
196     /**
197      * @brief Reads the Target property and stores in _tachTarget.
198      *        Also calls Fan::tachChanged().
199      *
200      * @param[in] msg - the dbus message
201      */
202     void handleTargetChange(sdbusplus::message::message& msg);
203 
204     /**
205      * @brief Reads the Value property and stores in _tachInput.
206      *        Also calls Fan::tachChanged().
207      *
208      * @param[in] msg - the dbus message
209      */
210     void handleTachChange(sdbusplus::message::message& msg);
211 
212     /**
213      * @brief Updates the Functional property in the inventory
214      *        for this tach sensor based on the value passed in.
215      *
216      * @param[in] functional - If the Functional property should
217      *                         be set to true or false.
218      */
219     void updateInventory(bool functional);
220 
221     /**
222      * @brief the dbus object
223      */
224     sdbusplus::bus::bus& _bus;
225 
226     /**
227      * @brief Reference to the parent Fan object
228      */
229     Fan& _fan;
230 
231     /**
232      * @brief The name of the sensor, including the full path
233      *
234      * For example /xyz/openbmc_project/sensors/fan_tach/fan0
235      */
236     const std::string _name;
237 
238     /**
239      * @brief The inventory name of the sensor, including the full path
240      */
241     const std::string _invName;
242 
243     /**
244      * @brief If functional (not too slow).  The parent
245      *        fan object sets this.
246      */
247     bool _functional;
248 
249     /**
250      * @brief If the sensor has a Target property (can set speed)
251      */
252     const bool _hasTarget;
253 
254     /**
255      * @brief Amount of time to delay updating to functional
256      */
257     const size_t _funcDelay;
258 
259     /**
260      * @brief The interface that the target implements
261      */
262     const std::string _interface;
263 
264     /**
265      * @brief The factor of target to get fan rpm
266      */
267     const double _factor;
268 
269     /**
270      * @brief The offset of target to get fan rpm
271      */
272     const int64_t _offset;
273 
274     /**
275      * @brief The input speed, from the Value dbus property
276      */
277     double _tachInput = 0;
278 
279     /**
280      * @brief The current target speed, from the Target dbus property
281      *        (if applicable)
282      */
283     uint64_t _tachTarget = 0;
284 
285     /**
286      * @brief The timeout value to use
287      */
288     const size_t _timeout;
289 
290     /**
291      * @brief Mode that current timer is in
292      */
293     TimerMode _timerMode;
294 
295     /**
296      * The timer object
297      */
298     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> _timer;
299 
300     /**
301      * @brief The match object for the Value properties changed signal
302      */
303     std::unique_ptr<sdbusplus::server::match::match> tachSignal;
304 
305     /**
306      * @brief The match object for the Target properties changed signal
307      */
308     std::unique_ptr<sdbusplus::server::match::match> targetSignal;
309 };
310 
311 } // namespace monitor
312 } // namespace fan
313 } // namespace phosphor
314