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 */ 58 explicit Group(const std::vector<GroupDefinition>& names) : _names(names) 59 {} 60 61 /** 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()) 77 { 78 _sensors.push_back({sensor, std::get<inTrust>(*found)}); 79 } 80 } 81 82 /** 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 } 97 98 /** 99 * Cancels monitoring on all sensors in the group. 100 * 101 * Called when the group just changed to not trusted, 102 * so that its sensors' monitoring method does not 103 * cause them to be considered faulted. 104 */ 105 void cancelMonitoring() 106 { 107 std::for_each(_sensors.begin(), _sensors.end(), 108 [](const auto& s) { s.sensor->resetMethod(); }); 109 } 110 111 /** 112 * Starts monitoring on all sensors in the group by processing their current 113 * state 114 * 115 * Called when the group just changed to trusted. 116 */ 117 void startMonitoring() 118 { 119 std::for_each(_sensors.begin(), _sensors.end(), 120 [](const auto& s) { s.sensor->processState(); }); 121 } 122 123 /** 124 * Determines the trust for this group based on this 125 * sensor's latest status. 126 * 127 * Calls the derived class's checkGroupTrust function 128 * and updates the class with the results. 129 * 130 * If this is called with a sensor not in the group, 131 * it will be considered trusted. 132 * 133 * @param[in] sensor - TachSensor object 134 * 135 * @return tuple<bool, bool> - 136 * field 0 - the trust value 137 * field 1 - if that trust value changed since last call 138 * to checkTrust 139 */ 140 auto checkTrust(const monitor::TachSensor& sensor) 141 { 142 if (inGroup(sensor)) 143 { 144 auto trust = checkGroupTrust(); 145 146 setTrust(trust); 147 148 return std::tuple<bool, bool>(_trusted, _stateChange); 149 } 150 return std::tuple<bool, bool>(true, false); 151 } 152 153 /** 154 * Says if all sensors in the group are currently trusted, 155 * as determined by the last call to checkTrust(). 156 * 157 * @return bool - if the group's sensors are trusted or not 158 */ 159 inline auto getTrust() const 160 { 161 return _trusted; 162 } 163 164 /** 165 * Says if the trust value changed in the last call to 166 * checkTrust() 167 * 168 * @return bool - if the trust changed or not 169 */ 170 inline auto trustChanged() const 171 { 172 return _stateChange; 173 } 174 175 protected: 176 /** 177 * The sensor objects and their trust inclusion in the group. 178 * 179 * Added by registerSensor(). 180 */ 181 std::vector<GroupSensor> _sensors; 182 183 private: 184 /** 185 * Checks if the group's sensors are trusted. 186 * 187 * The derived class must override this function 188 * to provide custom functionality. 189 * 190 * @return bool - if group is trusted or not 191 */ 192 virtual bool checkGroupTrust() = 0; 193 194 /** 195 * Sets the trust value on the object. 196 * 197 * @param[in] trust - the new trust value 198 */ 199 inline void setTrust(bool trust) 200 { 201 _stateChange = (trust != _trusted); 202 _trusted = trust; 203 } 204 205 /** 206 * The current trust state of the group 207 */ 208 bool _trusted = true; 209 210 /** 211 * If the trust value changed in the last call to checkTrust 212 */ 213 bool _stateChange = false; 214 215 /** 216 * The names of the sensors and whether it is included in 217 * determining trust for this group 218 */ 219 const std::vector<GroupDefinition> _names; 220 }; // namespace trust 221 222 } // namespace trust 223 } // namespace fan 224 } // namespace phosphor 225