blob: e9367e2d18f9657b6c35216bc4e112551f123100 [file] [log] [blame]
Matt Spinler78689dd2017-09-28 10:12:07 -05001#pragma once
Matt Spinler78689dd2017-09-28 10:12:07 -05002#include "tach_sensor.hpp"
3
Matthew Barth177fe982020-05-26 11:05:19 -05004#include <memory>
5
Matt Spinler78689dd2017-09-28 10:12:07 -05006namespace phosphor
7{
8namespace fan
9{
10namespace trust
11{
12
Matthew Barth6f31d192018-01-30 13:06:27 -060013constexpr auto sensorName = 0;
14constexpr auto inTrust = 1;
Matthew Barth177fe982020-05-26 11:05:19 -050015using GroupDefinition = std::tuple<std::string, bool>;
Matthew Barth6f31d192018-01-30 13:06:27 -060016
Matthew Bartha1c88322018-02-16 12:38:27 -060017struct GroupSensor
18{
19 std::shared_ptr<monitor::TachSensor> sensor;
20 bool inTrust;
21};
22
Matt Spinler78689dd2017-09-28 10:12:07 -050023/**
24 * @class Group
25 *
26 * An abstract sensor trust group base class.
27 *
28 * Supports the ability to know if a fan speed sensor value can
29 * be trusted or not, where if it isn't trusted then it shouldn't
30 * be used to determine if the fan is faulted or not.
31 *
32 * It's a group in that there can be multiple sensors in the group
33 * and the trust of all sensors depends on something about those sensors.
34 * For example, if all sensors in the group report a speed of zero,
35 * then no sensor in the group is trusted. All sensors in the group
36 * have the same trust value.
37 *
38 * Trust is calculated when checkTrust() is called after a group
39 * sensor's tach value changes.
40 *
41 * A derived class must override checkGroupTrust().
42 */
43class Group
44{
Matthew Barth177fe982020-05-26 11:05:19 -050045 public:
46 Group() = delete;
47 virtual ~Group() = default;
48 Group(const Group&) = delete;
49 Group& operator=(const Group&) = delete;
50 Group(Group&&) = default;
51 Group& operator=(Group&&) = default;
Matt Spinler78689dd2017-09-28 10:12:07 -050052
Matthew Barth177fe982020-05-26 11:05:19 -050053 /**
54 * Constructor
55 *
56 * @param[in] names - the names and inclusion of sensors in the group
57 */
58 explicit Group(const std::vector<GroupDefinition>& names) : _names(names)
59 {}
Matt Spinler78689dd2017-09-28 10:12:07 -050060
Matthew Barth177fe982020-05-26 11:05:19 -050061 /**
62 * Used to register a TachSensor object with the group.
63 * It's only added to the group if the sensor's name is
64 * in the group's list of names.
65 *
66 * @param[in] sensor - the TachSensor to register
67 */
68 void registerSensor(std::shared_ptr<monitor::TachSensor>& sensor)
69 {
70 auto found = std::find_if(
71 _names.begin(), _names.end(), [&sensor](const auto& name) {
72 return monitor::FAN_SENSOR_PATH + std::get<sensorName>(name) ==
73 sensor->name();
74 });
75
76 if (found != _names.end())
Matt Spinler78689dd2017-09-28 10:12:07 -050077 {
Matthew Barth177fe982020-05-26 11:05:19 -050078 _sensors.push_back({sensor, std::get<inTrust>(*found)});
Matt Spinler78689dd2017-09-28 10:12:07 -050079 }
Matthew Barth177fe982020-05-26 11:05:19 -050080 }
Matt Spinler78689dd2017-09-28 10:12:07 -050081
Matthew Barth177fe982020-05-26 11:05:19 -050082 /**
83 * Says if a sensor belongs to the group.
84 *
85 * After all sensors have registered, this can be
86 * used to say if a TachSensor is in the group.
87 *
88 * @param[in] sensor - the TachSensor object
89 */
90 bool inGroup(const monitor::TachSensor& sensor)
91 {
92 return (std::find_if(_sensors.begin(), _sensors.end(),
93 [&sensor](const auto& s) {
94 return sensor.name() == s.sensor->name();
95 }) != _sensors.end());
96 }
Matt Spinler78689dd2017-09-28 10:12:07 -050097
Matthew Barth177fe982020-05-26 11:05:19 -050098 /**
99 * Stops the timers on all sensors in the group.
100 *
101 * Called when the group just changed to not trusted,
102 * so that its sensors' timers can't fire a callback
103 * that may cause them to be considered faulted.
104 */
105 void stopTimers()
106 {
107 std::for_each(_sensors.begin(), _sensors.end(),
108 [](const auto& s) { s.sensor->stopTimer(); });
109 }
110
111 /**
112 * Starts the timers on all functional sensors in the group if
113 * their target and input values do not match.
114 *
115 * Called when the group just changed to trusted.
116 */
117 void startTimers()
118 {
119 std::for_each(_sensors.begin(), _sensors.end(), [](const auto& s) {
120 // If a sensor isn't functional, then its timer
121 // already expired so don't bother starting it again
122 if (s.sensor->functional() &&
123 static_cast<uint64_t>(s.sensor->getInput()) !=
124 s.sensor->getTarget())
Matt Spinler78689dd2017-09-28 10:12:07 -0500125 {
Matthew Barth177fe982020-05-26 11:05:19 -0500126 s.sensor->startTimer(
127 phosphor::fan::monitor::TimerMode::nonfunc);
Matt Spinler78689dd2017-09-28 10:12:07 -0500128 }
Matthew Barth177fe982020-05-26 11:05:19 -0500129 });
130 }
Matt Spinler78689dd2017-09-28 10:12:07 -0500131
Matthew Barth177fe982020-05-26 11:05:19 -0500132 /**
133 * Determines the trust for this group based on this
134 * sensor's latest status.
135 *
136 * Calls the derived class's checkGroupTrust function
137 * and updates the class with the results.
138 *
139 * If this is called with a sensor not in the group,
140 * it will be considered trusted.
141 *
142 * @param[in] sensor - TachSensor object
143 *
144 * @return tuple<bool, bool> -
145 * field 0 - the trust value
146 * field 1 - if that trust value changed since last call
147 * to checkTrust
148 */
149 auto checkTrust(const monitor::TachSensor& sensor)
150 {
151 if (inGroup(sensor))
Matt Spinler78689dd2017-09-28 10:12:07 -0500152 {
Matthew Barth177fe982020-05-26 11:05:19 -0500153 auto trust = checkGroupTrust();
154
155 setTrust(trust);
156
157 return std::tuple<bool, bool>(_trusted, _stateChange);
Matt Spinler78689dd2017-09-28 10:12:07 -0500158 }
Matthew Barth177fe982020-05-26 11:05:19 -0500159 return std::tuple<bool, bool>(true, false);
160 }
Matt Spinler78689dd2017-09-28 10:12:07 -0500161
Matthew Barth177fe982020-05-26 11:05:19 -0500162 /**
163 * Says if all sensors in the group are currently trusted,
164 * as determined by the last call to checkTrust().
165 *
166 * @return bool - if the group's sensors are trusted or not
167 */
168 inline auto getTrust() const
169 {
170 return _trusted;
171 }
Matt Spinler78689dd2017-09-28 10:12:07 -0500172
Matthew Barth177fe982020-05-26 11:05:19 -0500173 /**
174 * Says if the trust value changed in the last call to
175 * checkTrust()
176 *
177 * @return bool - if the trust changed or not
178 */
179 inline auto trustChanged() const
180 {
181 return _stateChange;
182 }
Matt Spinler78689dd2017-09-28 10:12:07 -0500183
Matthew Barth177fe982020-05-26 11:05:19 -0500184 protected:
185 /**
186 * The sensor objects and their trust inclusion in the group.
187 *
188 * Added by registerSensor().
189 */
190 std::vector<GroupSensor> _sensors;
Matt Spinler78689dd2017-09-28 10:12:07 -0500191
Matthew Barth177fe982020-05-26 11:05:19 -0500192 private:
193 /**
194 * Checks if the group's sensors are trusted.
195 *
196 * The derived class must override this function
197 * to provide custom functionality.
198 *
199 * @return bool - if group is trusted or not
200 */
201 virtual bool checkGroupTrust() = 0;
Matt Spinler78689dd2017-09-28 10:12:07 -0500202
Matthew Barth177fe982020-05-26 11:05:19 -0500203 /**
204 * Sets the trust value on the object.
205 *
206 * @param[in] trust - the new trust value
207 */
208 inline void setTrust(bool trust)
209 {
210 _stateChange = (trust != _trusted);
211 _trusted = trust;
212 }
Matt Spinler78689dd2017-09-28 10:12:07 -0500213
Matthew Barth177fe982020-05-26 11:05:19 -0500214 /**
215 * The current trust state of the group
216 */
217 bool _trusted = true;
Matt Spinler78689dd2017-09-28 10:12:07 -0500218
Matthew Barth177fe982020-05-26 11:05:19 -0500219 /**
220 * If the trust value changed in the last call to checkTrust
221 */
222 bool _stateChange = false;
Matt Spinler78689dd2017-09-28 10:12:07 -0500223
Matthew Barth177fe982020-05-26 11:05:19 -0500224 /**
225 * The names of the sensors and whether it is included in
226 * determining trust for this group
227 */
228 const std::vector<GroupDefinition> _names;
Matt Spinler78689dd2017-09-28 10:12:07 -0500229};
230
Matthew Barth177fe982020-05-26 11:05:19 -0500231} // namespace trust
232} // namespace fan
233} // namespace phosphor