blob: 001076b713870d12edc542e8c864ec8d00586ffc [file] [log] [blame]
#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