| #pragma once |
| #include "tach_sensor.hpp" |
| |
| #include <memory> |
| |
| 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()); |
| } |
| |
| /** |
| * Cancels monitoring on all sensors in the group. |
| * |
| * Called when the group just changed to not trusted, |
| * so that its sensors' monitoring method does not |
| * cause them to be considered faulted. |
| */ |
| void cancelMonitoring() |
| { |
| std::for_each(_sensors.begin(), _sensors.end(), |
| [](const auto& s) { s.sensor->resetMethod(); }); |
| } |
| |
| /** |
| * Starts monitoring on all sensors in the group by processing their current |
| * state |
| * |
| * Called when the group just changed to trusted. |
| */ |
| void startMonitoring() |
| { |
| std::for_each(_sensors.begin(), _sensors.end(), |
| [](const auto& s) { s.sensor->processState(); }); |
| } |
| |
| /** |
| * 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; |
| }; // namespace trust |
| |
| } // namespace trust |
| } // namespace fan |
| } // namespace phosphor |