| #pragma once | 
 | #include <memory> | 
 | #include "tach_sensor.hpp" | 
 |  | 
 | namespace phosphor | 
 | { | 
 | namespace fan | 
 | { | 
 | namespace trust | 
 | { | 
 |  | 
 | constexpr auto sensorName = 0; | 
 | constexpr auto inTrust = 1; | 
 | using GroupDefinition = std::tuple<std::string, | 
 |                                         bool>; | 
 |  | 
 | struct GroupSensor | 
 | { | 
 |     std::shared_ptr<monitor::TachSensor> sensor; | 
 |     bool inTrust; | 
 | }; | 
 |  | 
 | /** | 
 |  * @class Group | 
 |  * | 
 |  * An abstract sensor trust group base class. | 
 |  * | 
 |  * Supports the ability to know if a fan speed sensor value can | 
 |  * be trusted or not, where if it isn't trusted then it shouldn't | 
 |  * be used to determine if the fan is faulted or not. | 
 |  * | 
 |  * It's a group in that there can be multiple sensors in the group | 
 |  * and the trust of all sensors depends on something about those sensors. | 
 |  * For example, if all sensors in the group report a speed of zero, | 
 |  * then no sensor in the group is trusted.  All sensors in the group | 
 |  * have the same trust value. | 
 |  * | 
 |  * Trust is calculated when checkTrust() is called after a group | 
 |  * sensor's tach value changes. | 
 |  * | 
 |  * A derived class must override checkGroupTrust(). | 
 |  */ | 
 | class Group | 
 | { | 
 |     public: | 
 |  | 
 |         Group() = delete; | 
 |         virtual ~Group() = default; | 
 |         Group(const Group&) = delete; | 
 |         Group& operator=(const Group&) = delete; | 
 |         Group(Group&&) = default; | 
 |         Group& operator=(Group&&) = default; | 
 |  | 
 |         /** | 
 |          * Constructor | 
 |          * | 
 |          * @param[in] names - the names and inclusion of sensors in the group | 
 |          */ | 
 |         explicit Group(const std::vector<GroupDefinition>& names) : | 
 |                 _names(names) | 
 |         { | 
 |         } | 
 |  | 
 |         /** | 
 |          * Used to register a TachSensor object with the group. | 
 |          * It's only added to the group if the sensor's name is | 
 |          * in the group's list of names. | 
 |          * | 
 |          * @param[in] sensor - the TachSensor to register | 
 |          */ | 
 |         void registerSensor(std::shared_ptr<monitor::TachSensor>& sensor) | 
 |         { | 
 |             auto found = std::find_if( | 
 |                     _names.begin(), | 
 |                     _names.end(), | 
 |                     [&sensor](const auto& name) | 
 |                     { | 
 |                         return monitor::FAN_SENSOR_PATH + | 
 |                                 std::get<sensorName>(name) == sensor->name(); | 
 |                     }); | 
 |  | 
 |             if (found != _names.end()) | 
 |             { | 
 |                 _sensors.push_back({sensor, std::get<inTrust>(*found)}); | 
 |             } | 
 |         } | 
 |  | 
 |         /** | 
 |          * Says if a sensor belongs to the group. | 
 |          * | 
 |          * After all sensors have registered, this can be | 
 |          * used to say if a TachSensor is in the group. | 
 |          * | 
 |          * @param[in] sensor - the TachSensor object | 
 |          */ | 
 |          bool inGroup(const monitor::TachSensor& sensor) | 
 |          { | 
 |              return (std::find_if( | 
 |                      _sensors.begin(), | 
 |                      _sensors.end(), | 
 |                      [&sensor](const auto& s) | 
 |                      { | 
 |                          return sensor.name() == s.sensor->name(); | 
 |                      }) != _sensors.end()); | 
 |          } | 
 |  | 
 |         /** | 
 |          * Stops the timers on all sensors in the group. | 
 |          * | 
 |          * Called when the group just changed to not trusted, | 
 |          * so that its sensors' timers can't fire a callback | 
 |          * that may cause them to be considered faulted. | 
 |          */ | 
 |         void stopTimers() | 
 |         { | 
 |             std::for_each( | 
 |                     _sensors.begin(), | 
 |                     _sensors.end(), | 
 |                     [](const auto& s) | 
 |                     { | 
 |                         s.sensor->stopTimer(); | 
 |                     }); | 
 |         } | 
 |  | 
 |         /** | 
 |          * Starts the timers on all functional sensors in the group if | 
 |          * their target and input values do not match. | 
 |          * | 
 |          * Called when the group just changed to trusted. | 
 |          */ | 
 |         void startTimers() | 
 |         { | 
 |             std::for_each( | 
 |                     _sensors.begin(), | 
 |                     _sensors.end(), | 
 |                     [](const auto& s) | 
 |                     { | 
 |                         //If a sensor isn't functional, then its timer | 
 |                         //already expired so don't bother starting it again | 
 |                         if (s.sensor->functional() && | 
 |                             static_cast<uint64_t>( | 
 |                                 s.sensor->getInput()) != | 
 |                                     s.sensor->getTarget()) | 
 |                         { | 
 |                             s.sensor->startTimer( | 
 |                                 phosphor::fan::monitor::TimerMode::nonfunc); | 
 |                         } | 
 |                     }); | 
 |         } | 
 |  | 
 |         /** | 
 |          * Determines the trust for this group based on this | 
 |          * sensor's latest status. | 
 |          * | 
 |          * Calls the derived class's checkGroupTrust function | 
 |          * and updates the class with the results. | 
 |          * | 
 |          * If this is called with a sensor not in the group, | 
 |          * it will be considered trusted. | 
 |          * | 
 |          * @param[in] sensor - TachSensor object | 
 |          * | 
 |          * @return tuple<bool, bool> - | 
 |          *   field 0 - the trust value | 
 |          *   field 1 - if that trust value changed since last call | 
 |          *             to checkTrust | 
 |          */ | 
 |         auto checkTrust(const monitor::TachSensor& sensor) | 
 |         { | 
 |             if (inGroup(sensor)) | 
 |             { | 
 |                 auto trust = checkGroupTrust(); | 
 |  | 
 |                 setTrust(trust); | 
 |  | 
 |                 return std::tuple<bool, bool>(_trusted, _stateChange); | 
 |             } | 
 |             return std::tuple<bool, bool>(true, false); | 
 |         } | 
 |  | 
 |         /** | 
 |          * Says if all sensors in the group are currently trusted, | 
 |          * as determined by the last call to checkTrust(). | 
 |          * | 
 |          * @return bool - if the group's sensors are trusted or not | 
 |          */ | 
 |         inline auto getTrust() const | 
 |         { | 
 |             return _trusted; | 
 |         } | 
 |  | 
 |         /** | 
 |          * Says if the trust value changed in the last call to | 
 |          * checkTrust() | 
 |          * | 
 |          * @return bool - if the trust changed or not | 
 |          */ | 
 |         inline auto trustChanged() const | 
 |         { | 
 |             return _stateChange; | 
 |         } | 
 |  | 
 |     protected: | 
 |  | 
 |         /** | 
 |          * The sensor objects and their trust inclusion in the group. | 
 |          * | 
 |          * Added by registerSensor(). | 
 |          */ | 
 |         std::vector<GroupSensor> _sensors; | 
 |  | 
 |     private: | 
 |  | 
 |         /** | 
 |          * Checks if the group's sensors are trusted. | 
 |          * | 
 |          * The derived class must override this function | 
 |          * to provide custom functionality. | 
 |          * | 
 |          * @return bool - if group is trusted or not | 
 |          */ | 
 |         virtual bool checkGroupTrust() = 0; | 
 |  | 
 |         /** | 
 |          * Sets the trust value on the object. | 
 |          * | 
 |          * @param[in] trust - the new trust value | 
 |          */ | 
 |         inline void setTrust(bool trust) | 
 |         { | 
 |             _stateChange = (trust != _trusted); | 
 |             _trusted = trust; | 
 |         } | 
 |  | 
 |         /** | 
 |          * The current trust state of the group | 
 |          */ | 
 |         bool _trusted = true; | 
 |  | 
 |         /** | 
 |          * If the trust value changed in the last call to checkTrust | 
 |          */ | 
 |         bool _stateChange = false; | 
 |  | 
 |         /** | 
 |          * The names of the sensors and whether it is included in | 
 |          * determining trust for this group | 
 |          */ | 
 |         const std::vector<GroupDefinition> _names; | 
 | }; | 
 |  | 
 | } | 
 | } | 
 | } |