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 constexpr auto sensorName = 0; 13 constexpr auto inTrust = 1; 14 using GroupDefinition = std::tuple<std::string, 15 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 47 Group() = delete; 48 virtual ~Group() = default; 49 Group(const Group&) = delete; 50 Group& operator=(const Group&) = delete; 51 Group(Group&&) = default; 52 Group& operator=(Group&&) = default; 53 54 /** 55 * Constructor 56 * 57 * @param[in] names - the names and inclusion of sensors in the group 58 */ 59 explicit Group(const std::vector<GroupDefinition>& names) : 60 _names(names) 61 { 62 } 63 64 /** 65 * Used to register a TachSensor object with the group. 66 * It's only added to the group if the sensor's name is 67 * in the group's list of names. 68 * 69 * @param[in] sensor - the TachSensor to register 70 */ 71 void registerSensor(std::shared_ptr<monitor::TachSensor>& sensor) 72 { 73 auto found = std::find_if( 74 _names.begin(), 75 _names.end(), 76 [&sensor](const auto& name) 77 { 78 return monitor::FAN_SENSOR_PATH + 79 std::get<sensorName>(name) == sensor->name(); 80 }); 81 82 if (found != _names.end()) 83 { 84 _sensors.push_back({sensor, std::get<inTrust>(*found)}); 85 } 86 } 87 88 /** 89 * Says if a sensor belongs to the group. 90 * 91 * After all sensors have registered, this can be 92 * used to say if a TachSensor is in the group. 93 * 94 * @param[in] sensor - the TachSensor object 95 */ 96 bool inGroup(const monitor::TachSensor& sensor) 97 { 98 return (std::find_if( 99 _sensors.begin(), 100 _sensors.end(), 101 [&sensor](const auto& s) 102 { 103 return sensor.name() == s.sensor->name(); 104 }) != _sensors.end()); 105 } 106 107 /** 108 * Stops the timers on all sensors in the group. 109 * 110 * Called when the group just changed to not trusted, 111 * so that its sensors' timers can't fire a callback 112 * that may cause them to be considered faulted. 113 */ 114 void stopTimers() 115 { 116 std::for_each( 117 _sensors.begin(), 118 _sensors.end(), 119 [](const auto& s) 120 { 121 s.sensor->stopTimer(); 122 }); 123 } 124 125 /** 126 * Starts the timers on all functional sensors in the group if 127 * their target and input values do not match. 128 * 129 * Called when the group just changed to trusted. 130 */ 131 void startTimers() 132 { 133 std::for_each( 134 _sensors.begin(), 135 _sensors.end(), 136 [](const auto& s) 137 { 138 //If a sensor isn't functional, then its timer 139 //already expired so don't bother starting it again 140 if (s.sensor->functional() && 141 static_cast<uint64_t>( 142 s.sensor->getInput()) != 143 s.sensor->getTarget()) 144 { 145 s.sensor->startTimer(); 146 } 147 }); 148 } 149 150 /** 151 * Determines the trust for this group based on this 152 * sensor's latest status. 153 * 154 * Calls the derived class's checkGroupTrust function 155 * and updates the class with the results. 156 * 157 * If this is called with a sensor not in the group, 158 * it will be considered trusted. 159 * 160 * @param[in] sensor - TachSensor object 161 * 162 * @return tuple<bool, bool> - 163 * field 0 - the trust value 164 * field 1 - if that trust value changed since last call 165 * to checkTrust 166 */ 167 auto checkTrust(const monitor::TachSensor& sensor) 168 { 169 if (inGroup(sensor)) 170 { 171 auto trust = checkGroupTrust(); 172 173 setTrust(trust); 174 175 return std::tuple<bool, bool>(_trusted, _stateChange); 176 } 177 return std::tuple<bool, bool>(true, false); 178 } 179 180 /** 181 * Says if all sensors in the group are currently trusted, 182 * as determined by the last call to checkTrust(). 183 * 184 * @return bool - if the group's sensors are trusted or not 185 */ 186 inline auto getTrust() const 187 { 188 return _trusted; 189 } 190 191 /** 192 * Says if the trust value changed in the last call to 193 * checkTrust() 194 * 195 * @return bool - if the trust changed or not 196 */ 197 inline auto trustChanged() const 198 { 199 return _stateChange; 200 } 201 202 protected: 203 204 /** 205 * The sensor objects and their trust inclusion in the group. 206 * 207 * Added by registerSensor(). 208 */ 209 std::vector<GroupSensor> _sensors; 210 211 private: 212 213 /** 214 * Checks if the group's sensors are trusted. 215 * 216 * The derived class must override this function 217 * to provide custom functionality. 218 * 219 * @return bool - if group is trusted or not 220 */ 221 virtual bool checkGroupTrust() = 0; 222 223 /** 224 * Sets the trust value on the object. 225 * 226 * @param[in] trust - the new trust value 227 */ 228 inline void setTrust(bool trust) 229 { 230 _stateChange = (trust != _trusted); 231 _trusted = trust; 232 } 233 234 /** 235 * The current trust state of the group 236 */ 237 bool _trusted = true; 238 239 /** 240 * If the trust value changed in the last call to checkTrust 241 */ 242 bool _stateChange = false; 243 244 /** 245 * The names of the sensors and whether it is included in 246 * determining trust for this group 247 */ 248 const std::vector<GroupDefinition> _names; 249 }; 250 251 } 252 } 253 } 254