1 #pragma once 2 #include <memory> 3 #include "tach_sensor.hpp" 4 5 namespace phosphor 6 { 7 namespace fan 8 { 9 namespace 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 */ 32 class 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 /** 115 * Starts the timers on all functional sensors in the group. 116 * 117 * Called when the group just changed to trusted. 118 */ 119 void startTimers() 120 { 121 std::for_each( 122 _sensors.begin(), 123 _sensors.end(), 124 [](const auto& s) 125 { 126 //If a sensor isn't functional, then its timer 127 //already expired so don't bother starting it again 128 if (s.get()->functional()) 129 { 130 s.get()->startTimer(); 131 } 132 }); 133 } 134 135 /** 136 * Determines the trust for this group based on this 137 * sensor's latest status. 138 * 139 * Calls the derived class's checkGroupTrust function 140 * and updates the class with the results. 141 * 142 * If this is called with a sensor not in the group, 143 * it will be considered trusted. 144 * 145 * @param[in] sensor - TachSensor object 146 * 147 * @return tuple<bool, bool> - 148 * field 0 - the trust value 149 * field 1 - if that trust value changed since last call 150 * to checkTrust 151 */ 152 auto checkTrust(const monitor::TachSensor& sensor) 153 { 154 if (inGroup(sensor)) 155 { 156 auto trust = checkGroupTrust(); 157 158 setTrust(trust); 159 160 return std::tuple<bool, bool>(_trusted, _stateChange); 161 } 162 return std::tuple<bool, bool>(true, false); 163 } 164 165 /** 166 * Says if all sensors in the group are currently trusted, 167 * as determined by the last call to checkTrust(). 168 * 169 * @return bool - if the group's sensors are trusted or not 170 */ 171 inline auto getTrust() const 172 { 173 return _trusted; 174 } 175 176 /** 177 * Says if the trust value changed in the last call to 178 * checkTrust() 179 * 180 * @return bool - if the trust changed or not 181 */ 182 inline auto trustChanged() const 183 { 184 return _stateChange; 185 } 186 187 protected: 188 189 /** 190 * The sensor objects in the group. 191 * 192 * Added by registerSensor(). 193 */ 194 std::vector<std::reference_wrapper< 195 std::unique_ptr<monitor::TachSensor>>> _sensors; 196 197 private: 198 199 /** 200 * Checks if the group's sensors are trusted. 201 * 202 * The derived class must override this function 203 * to provide custom functionality. 204 * 205 * @return bool - if group is trusted or not 206 */ 207 virtual bool checkGroupTrust() = 0; 208 209 /** 210 * Sets the trust value on the object. 211 * 212 * @param[in] trust - the new trust value 213 */ 214 inline void setTrust(bool trust) 215 { 216 _stateChange = (trust != _trusted); 217 _trusted = trust; 218 } 219 220 /** 221 * The current trust state of the group 222 */ 223 bool _trusted = true; 224 225 /** 226 * If the trust value changed in the last call to checkTrust 227 */ 228 bool _stateChange = false; 229 230 /** 231 * The names of the sensors that should be added to this group 232 */ 233 const std::vector<std::string> _names; 234 }; 235 236 } 237 } 238 } 239