From 78689dd7cf10b8161ba04a2e9dc22b923baf5aa7 Mon Sep 17 00:00:00 2001 From: Matt Spinler Date: Thu, 28 Sep 2017 10:12:07 -0500 Subject: monitor: Add tach sensor trust group class The trust::Group class is an abstract base class that introduces the concept of knowing if a tach sensor reading can be trusted or not. If it isn't trusted, then it shouldn't be used when calculating if the fan is considered functional or not. It's a group because it supports groups of sensors all having the same trusted status. For example the first use case is a group of sensors cannot be trusted when all of their readings are zero. A group may of course just have 1 sensor in it if required. The class also provides the functionality to start and stop the timers that are used to consider a sensor faulted. The timers would be stopped when a group moves to untrusted, and started when it goes back to the trusted state. Derived classes provide the functionality that actually determines the trust value. The constructor takes the list of sensor names that should be in the group. After the TachSensor classes have been constructed, the registerSensor(sensor) function must be called to add the sensor objects to the group. The checkTrust() function is used to calculate the trust status of the group. Change-Id: Ib4b871c6a186105028d1cc186c49611fb0608325 Signed-off-by: Matt Spinler --- monitor/tach_sensor.cpp | 1 - monitor/tach_sensor.hpp | 1 + monitor/trust_group.hpp | 238 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 239 insertions(+), 1 deletion(-) create mode 100644 monitor/trust_group.hpp diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp index 9a98e37..040e8f9 100644 --- a/monitor/tach_sensor.cpp +++ b/monitor/tach_sensor.cpp @@ -26,7 +26,6 @@ namespace fan namespace monitor { -constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/"; constexpr auto FAN_SENSOR_CONTROL_INTF = "xyz.openbmc_project.Control.FanSpeed"; constexpr auto FAN_SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value"; constexpr auto FAN_TARGET_PROPERTY = "Target"; diff --git a/monitor/tach_sensor.hpp b/monitor/tach_sensor.hpp index 60a55e3..9b10110 100644 --- a/monitor/tach_sensor.hpp +++ b/monitor/tach_sensor.hpp @@ -15,6 +15,7 @@ namespace monitor class Fan; +constexpr auto FAN_SENSOR_PATH = "/xyz/openbmc_project/sensors/fan_tach/"; /** * @class TachSensor diff --git a/monitor/trust_group.hpp b/monitor/trust_group.hpp new file mode 100644 index 0000000..af7b372 --- /dev/null +++ b/monitor/trust_group.hpp @@ -0,0 +1,238 @@ +#pragma once +#include +#include "tach_sensor.hpp" + +namespace phosphor +{ +namespace fan +{ +namespace trust +{ + +/** + * @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 of the sensors in the group + */ + explicit Group(const std::vector& 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::unique_ptr& sensor) + { + auto found = std::find_if( + _names.begin(), + _names.end(), + [&sensor](const auto& name) + { + return monitor::FAN_SENSOR_PATH + + name == sensor->name(); + }); + + if (found != _names.end()) + { + _sensors.push_back(sensor); + } + } + + /** + * 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.get()->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.get()->stopTimer(); + }); + } + + /** + * Starts the timers on all functional sensors in the group. + * + * 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.get()->functional()) + { + s.get()->startTimer(); + } + }); + } + + /** + * 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 - + * 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(_trusted, _stateChange); + } + return std::tuple(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 in the group. + * + * Added by registerSensor(). + */ + std::vector>> _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 that should be added to this group + */ + const std::vector _names; +}; + +} +} +} -- cgit v1.2.1