1 #pragma once 2 #include "tach_sensor.hpp" 3 4 #include <memory> 5 6 namespace phosphor 7 { 8 namespace fan 9 { 10 namespace trust 11 { 12 13 constexpr auto sensorName = 0; 14 constexpr auto inTrust = 1; 15 using GroupDefinition = std::tuple<std::string, bool>; 16 17 struct GroupSensor 18 { 19 std::shared_ptr<monitor::TachSensor> sensor; 20 bool inTrust; 21 }; 22 23 /** 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 */ 43 class Group 44 { 45 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; 52 53 /** 54 * Constructor 55 * 56 * @param[in] names - the names and inclusion of sensors in the group 57 */ Group(const std::vector<GroupDefinition> & names)58 explicit Group(const std::vector<GroupDefinition>& names) : _names(names) {} 59 60 /** 61 * Used to register a TachSensor object with the group. 62 * It's only added to the group if the sensor's name is 63 * in the group's list of names. 64 * 65 * @param[in] sensor - the TachSensor to register 66 */ registerSensor(std::shared_ptr<monitor::TachSensor> & sensor)67 void registerSensor(std::shared_ptr<monitor::TachSensor>& sensor) 68 { 69 auto found = std::find_if( 70 _names.begin(), _names.end(), [&sensor](const auto& name) { 71 return monitor::FAN_SENSOR_PATH + std::get<sensorName>(name) == 72 sensor->name(); 73 }); 74 75 if (found != _names.end()) 76 { 77 _sensors.push_back({sensor, std::get<inTrust>(*found)}); 78 } 79 } 80 81 /** 82 * Says if a sensor belongs to the group. 83 * 84 * After all sensors have registered, this can be 85 * used to say if a TachSensor is in the group. 86 * 87 * @param[in] sensor - the TachSensor object 88 */ inGroup(const monitor::TachSensor & sensor)89 bool inGroup(const monitor::TachSensor& sensor) 90 { 91 return (std::find_if(_sensors.begin(), _sensors.end(), 92 [&sensor](const auto& s) { 93 return sensor.name() == s.sensor->name(); 94 }) != _sensors.end()); 95 } 96 97 /** 98 * Cancels monitoring on all sensors in the group. 99 * 100 * Called when the group just changed to not trusted, 101 * so that its sensors' monitoring method does not 102 * cause them to be considered faulted. 103 */ cancelMonitoring()104 void cancelMonitoring() 105 { 106 std::for_each(_sensors.begin(), _sensors.end(), 107 [](const auto& s) { s.sensor->resetMethod(); }); 108 } 109 110 /** 111 * Starts monitoring on all sensors in the group by processing their current 112 * state 113 * 114 * Called when the group just changed to trusted. 115 */ startMonitoring()116 void startMonitoring() 117 { 118 std::for_each(_sensors.begin(), _sensors.end(), 119 [](const auto& s) { s.sensor->processState(); }); 120 } 121 122 /** 123 * Determines the trust for this group based on this 124 * sensor's latest status. 125 * 126 * Calls the derived class's checkGroupTrust function 127 * and updates the class with the results. 128 * 129 * If this is called with a sensor not in the group, 130 * it will be considered trusted. 131 * 132 * @param[in] sensor - TachSensor object 133 * 134 * @return tuple<bool, bool> - 135 * field 0 - the trust value 136 * field 1 - if that trust value changed since last call 137 * to checkTrust 138 */ checkTrust(const monitor::TachSensor & sensor)139 auto checkTrust(const monitor::TachSensor& sensor) 140 { 141 if (inGroup(sensor)) 142 { 143 auto trust = checkGroupTrust(); 144 145 setTrust(trust); 146 147 return std::tuple<bool, bool>(_trusted, _stateChange); 148 } 149 return std::tuple<bool, bool>(true, false); 150 } 151 152 /** 153 * Says if all sensors in the group are currently trusted, 154 * as determined by the last call to checkTrust(). 155 * 156 * @return bool - if the group's sensors are trusted or not 157 */ getTrust() const158 inline auto getTrust() const 159 { 160 return _trusted; 161 } 162 163 /** 164 * Says if the trust value changed in the last call to 165 * checkTrust() 166 * 167 * @return bool - if the trust changed or not 168 */ trustChanged() const169 inline auto trustChanged() const 170 { 171 return _stateChange; 172 } 173 174 protected: 175 /** 176 * The sensor objects and their trust inclusion in the group. 177 * 178 * Added by registerSensor(). 179 */ 180 std::vector<GroupSensor> _sensors; 181 182 private: 183 /** 184 * Checks if the group's sensors are trusted. 185 * 186 * The derived class must override this function 187 * to provide custom functionality. 188 * 189 * @return bool - if group is trusted or not 190 */ 191 virtual bool checkGroupTrust() = 0; 192 193 /** 194 * Sets the trust value on the object. 195 * 196 * @param[in] trust - the new trust value 197 */ setTrust(bool trust)198 inline void setTrust(bool trust) 199 { 200 _stateChange = (trust != _trusted); 201 _trusted = trust; 202 } 203 204 /** 205 * The current trust state of the group 206 */ 207 bool _trusted = true; 208 209 /** 210 * If the trust value changed in the last call to checkTrust 211 */ 212 bool _stateChange = false; 213 214 /** 215 * The names of the sensors and whether it is included in 216 * determining trust for this group 217 */ 218 const std::vector<GroupDefinition> _names; 219 }; // namespace trust 220 221 } // namespace trust 222 } // namespace fan 223 } // namespace phosphor 224