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 if 116 * their target and input values do not match. 117 * 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 129 if (s.get()->functional() && 130 static_cast<uint64_t>(s.get()->getInput()) != 131 s.get()->getTarget()) 132 { 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 } 242