blob: e0db5c9f2531b2c340bbd4260c0efa285d2d55ce [file] [log] [blame]
Matt Spinler78689dd2017-09-28 10:12:07 -05001#pragma once
2#include <memory>
3#include "tach_sensor.hpp"
4
5namespace phosphor
6{
7namespace fan
8{
9namespace trust
10{
11
12/**
13 * @class Group
14 *
15 * An abstract sensor trust group base class.
16 *
17 * Supports the ability to know if a fan speed sensor value can
18 * be trusted or not, where if it isn't trusted then it shouldn't
19 * be used to determine if the fan is faulted or not.
20 *
21 * It's a group in that there can be multiple sensors in the group
22 * and the trust of all sensors depends on something about those sensors.
23 * For example, if all sensors in the group report a speed of zero,
24 * then no sensor in the group is trusted. All sensors in the group
25 * have the same trust value.
26 *
27 * Trust is calculated when checkTrust() is called after a group
28 * sensor's tach value changes.
29 *
30 * A derived class must override checkGroupTrust().
31 */
32class Group
33{
34 public:
35
36 Group() = delete;
37 virtual ~Group() = default;
38 Group(const Group&) = delete;
39 Group& operator=(const Group&) = delete;
40 Group(Group&&) = default;
41 Group& operator=(Group&&) = default;
42
43 /**
44 * Constructor
45 *
46 * @param[in] names - the names of the sensors in the group
47 */
48 explicit Group(const std::vector<std::string>& names) :
49 _names(names)
50 {
51 }
52
53 /**
54 * Used to register a TachSensor object with the group.
55 * It's only added to the group if the sensor's name is
56 * in the group's list of names.
57 *
58 * @param[in] sensor - the TachSensor to register
59 */
60 void registerSensor(std::unique_ptr<monitor::TachSensor>& sensor)
61 {
62 auto found = std::find_if(
63 _names.begin(),
64 _names.end(),
65 [&sensor](const auto& name)
66 {
67 return monitor::FAN_SENSOR_PATH +
68 name == sensor->name();
69 });
70
71 if (found != _names.end())
72 {
73 _sensors.push_back(sensor);
74 }
75 }
76
77 /**
78 * Says if a sensor belongs to the group.
79 *
80 * After all sensors have registered, this can be
81 * used to say if a TachSensor is in the group.
82 *
83 * @param[in] sensor - the TachSensor object
84 */
85 bool inGroup(const monitor::TachSensor& sensor)
86 {
87 return (std::find_if(
88 _sensors.begin(),
89 _sensors.end(),
90 [&sensor](const auto& s)
91 {
92 return sensor.name() == s.get()->name();
93 }) != _sensors.end());
94 }
95
96 /**
97 * Stops the timers on all sensors in the group.
98 *
99 * Called when the group just changed to not trusted,
100 * so that its sensors' timers can't fire a callback
101 * that may cause them to be considered faulted.
102 */
103 void stopTimers()
104 {
105 std::for_each(
106 _sensors.begin(),
107 _sensors.end(),
108 [](const auto& s)
109 {
110 s.get()->stopTimer();
111 });
112 }
113
114 /**
Matthew Barth58560232017-11-22 14:52:12 -0600115 * Starts the timers on all functional sensors in the group if
116 * their target and input values do not match.
Matt Spinler78689dd2017-09-28 10:12:07 -0500117 *
118 * Called when the group just changed to trusted.
119 */
120 void startTimers()
121 {
122 std::for_each(
123 _sensors.begin(),
124 _sensors.end(),
125 [](const auto& s)
126 {
127 //If a sensor isn't functional, then its timer
128 //already expired so don't bother starting it again
Matthew Barth58560232017-11-22 14:52:12 -0600129 if (s.get()->functional() &&
130 static_cast<uint64_t>(s.get()->getInput()) !=
131 s.get()->getTarget())
Matt Spinler78689dd2017-09-28 10:12:07 -0500132 {
133 s.get()->startTimer();
134 }
135 });
136 }
137
138 /**
139 * Determines the trust for this group based on this
140 * sensor's latest status.
141 *
142 * Calls the derived class's checkGroupTrust function
143 * and updates the class with the results.
144 *
145 * If this is called with a sensor not in the group,
146 * it will be considered trusted.
147 *
148 * @param[in] sensor - TachSensor object
149 *
150 * @return tuple<bool, bool> -
151 * field 0 - the trust value
152 * field 1 - if that trust value changed since last call
153 * to checkTrust
154 */
155 auto checkTrust(const monitor::TachSensor& sensor)
156 {
157 if (inGroup(sensor))
158 {
159 auto trust = checkGroupTrust();
160
161 setTrust(trust);
162
163 return std::tuple<bool, bool>(_trusted, _stateChange);
164 }
165 return std::tuple<bool, bool>(true, false);
166 }
167
168 /**
169 * Says if all sensors in the group are currently trusted,
170 * as determined by the last call to checkTrust().
171 *
172 * @return bool - if the group's sensors are trusted or not
173 */
174 inline auto getTrust() const
175 {
176 return _trusted;
177 }
178
179 /**
180 * Says if the trust value changed in the last call to
181 * checkTrust()
182 *
183 * @return bool - if the trust changed or not
184 */
185 inline auto trustChanged() const
186 {
187 return _stateChange;
188 }
189
190 protected:
191
192 /**
193 * The sensor objects in the group.
194 *
195 * Added by registerSensor().
196 */
197 std::vector<std::reference_wrapper<
198 std::unique_ptr<monitor::TachSensor>>> _sensors;
199
200 private:
201
202 /**
203 * Checks if the group's sensors are trusted.
204 *
205 * The derived class must override this function
206 * to provide custom functionality.
207 *
208 * @return bool - if group is trusted or not
209 */
210 virtual bool checkGroupTrust() = 0;
211
212 /**
213 * Sets the trust value on the object.
214 *
215 * @param[in] trust - the new trust value
216 */
217 inline void setTrust(bool trust)
218 {
219 _stateChange = (trust != _trusted);
220 _trusted = trust;
221 }
222
223 /**
224 * The current trust state of the group
225 */
226 bool _trusted = true;
227
228 /**
229 * If the trust value changed in the last call to checkTrust
230 */
231 bool _stateChange = false;
232
233 /**
234 * The names of the sensors that should be added to this group
235 */
236 const std::vector<std::string> _names;
237};
238
239}
240}
241}