1 #pragma once
2 
3 #include "fan.hpp"
4 #include "power_state.hpp"
5 #include "rpolicy.hpp"
6 
7 #include <sdeventplus/utility/timer.hpp>
8 
9 #include <functional>
10 #include <vector>
11 
12 namespace phosphor
13 {
14 namespace fan
15 {
16 namespace presence
17 {
18 
19 class PresenceSensor;
20 
21 /**
22  * @class AnyOf
23  * @brief AnyOf redundancy policy.
24  *
25  * The any of redundancy policy monitors all sensor
26  * states in the redundancy set and reports true when any
27  * sensor in the set reports true.
28  */
29 class AnyOf : public RedundancyPolicy
30 {
31   public:
32     AnyOf() = delete;
33     AnyOf(const AnyOf&) = default;
34     AnyOf& operator=(const AnyOf&) = default;
35     AnyOf(AnyOf&&) = default;
36     AnyOf& operator=(AnyOf&&) = default;
37     ~AnyOf() = default;
38 
39     /**
40      * @brief Construct an any of bitwise policy.
41      *
42      * @param[in] fan - The fan associated with the policy.
43      * @param[in] s - The set of sensors associated with the policy.
44      */
45     AnyOf(const Fan& fan,
46           const std::vector<std::reference_wrapper<PresenceSensor>>& s);
47 
48     /**
49      * @brief stateChanged
50      *
51      * Update the inventory and execute the fallback
52      * policy.
53      *
54      * @param[in] present - The new presence state according
55      *             to the specified sensor.
56      * @param[in] sensor - The sensor reporting the new state.
57      */
58     void stateChanged(bool present, PresenceSensor& sensor) override;
59 
60     /**
61      * @brief monitor
62      *
63      * Start monitoring the fan.
64      */
65     void monitor() override;
66 
67   private:
68     /**
69      * @brief Checks that the sensors contained in this policy all
70      *        agree on the presence value.  If they don't, then call
71      *        logConflict() on the sensors that don't think the fan
72      *        is present as they may be broken.
73      *
74      * This check will only happen when power is on.
75      */
76     void checkSensorConflicts();
77 
78     /**
79      * @brief Callback function called after a post-poweron delay.
80      *
81      * The _powerOnDelayTimer is started when _powerState says the
82      * power is on to give fans a bit of time to spin up so tachs
83      * wouldn't be zero.  This is the callback function for that timer.
84      *
85      * It will call checkSensorConflicts().
86      */
87     void delayedAfterPowerOn();
88 
89     /**
90      * @brief Says if power is on, though not until the post
91      *        power on delay is complete.
92      *
93      * @return bool - if power is on.
94      */
95     inline bool isPowerOn() const
96     {
97         return _powerOn;
98     }
99 
100     /**
101      * @brief Called by the PowerState object when the power
102      *        state changes.
103      *
104      * When power changes to on:
105      *   - Clears the memory of previous sensor conflicts.
106      *   - Starts the post power on delay timer.
107      *
108      * @param[in] powerOn - If power is now on or off.
109      */
110     void powerStateChanged(bool powerOn);
111 
112     static constexpr size_t sensorPos = 0;
113     static constexpr size_t presentPos = 1;
114     static constexpr size_t conflictPos = 2;
115 
116     /**
117      * @brief All presence sensors in the redundancy set.
118      *
119      * Each entry contains:
120      *  - A reference to a PresenceSensor
121      *  - The current presence state
122      *  - If the sensors have logged conflicts in their answers.
123      */
124     std::vector<std::tuple<std::reference_wrapper<PresenceSensor>, bool, bool>>
125         state;
126 
127     /**
128      * @brief Pointer to the PowerState object used to track power changes.
129      */
130     std::shared_ptr<PowerState> _powerState;
131 
132     /**
133      * @brief Post power on delay timer, where the conflict checking code
134      *        doesn't consider power on until this timer expires.
135      *
136      * This gives fans a chance to start spinning before checking them.
137      */
138     sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>
139         _powerOnDelayTimer;
140 
141     /**
142      * @brief Current power state.
143      */
144     bool _powerOn;
145 };
146 
147 } // namespace presence
148 } // namespace fan
149 } // namespace phosphor
150