xref: /openbmc/phosphor-hwmon/thresholds.hpp (revision 5906173aec2a48f37d1356f1ade788c8d25530b2)
1 #pragma once
2 
3 #include "env.hpp"
4 #include "interface.hpp"
5 
6 #include <cmath>
7 
8 /** @class Thresholds
9  *  @brief Threshold type traits.
10  *
11  *  @tparam T - The threshold type.
12  */
13 template <typename T>
14 struct Thresholds
15 {
16     static void fail()
17     {
18         static_assert(sizeof(Thresholds) == -1, "Unsupported Threshold type");
19     }
20 };
21 
22 /**@brief Thresholds specialization for warning thresholds. */
23 template <>
24 struct Thresholds<WarningObject>
25 {
26     static constexpr InterfaceType type = InterfaceType::WARN;
27     static constexpr const char* envLo = "WARNLO";
28     static constexpr const char* envHi = "WARNHI";
29     static SensorValueType (WarningObject::*const setLo)(SensorValueType);
30     static SensorValueType (WarningObject::*const setHi)(SensorValueType);
31     static SensorValueType (WarningObject::*const getLo)() const;
32     static SensorValueType (WarningObject::*const getHi)() const;
33     static bool (WarningObject::*const alarmLo)(bool);
34     static bool (WarningObject::*const alarmHi)(bool);
35 };
36 
37 /**@brief Thresholds specialization for critical thresholds. */
38 template <>
39 struct Thresholds<CriticalObject>
40 {
41     static constexpr InterfaceType type = InterfaceType::CRIT;
42     static constexpr const char* envLo = "CRITLO";
43     static constexpr const char* envHi = "CRITHI";
44     static SensorValueType (CriticalObject::*const setLo)(SensorValueType);
45     static SensorValueType (CriticalObject::*const setHi)(SensorValueType);
46     static SensorValueType (CriticalObject::*const getLo)() const;
47     static SensorValueType (CriticalObject::*const getHi)() const;
48     static bool (CriticalObject::*const alarmLo)(bool);
49     static bool (CriticalObject::*const alarmHi)(bool);
50 };
51 
52 /** @brief checkThresholds
53  *
54  *  Compare a sensor reading to threshold values and set the
55  *  appropriate alarm property if bounds are exceeded.
56  *
57  *  @tparam T - The threshold type.
58  *
59  *  @param[in] iface - An sdbusplus server threshold instance.
60  *  @param[in] value - The sensor reading to compare to thresholds.
61  */
62 template <typename T>
63 void checkThresholds(std::any& iface, SensorValueType value)
64 {
65     auto realIface = std::any_cast<std::shared_ptr<T>>(iface);
66     auto lo = (*realIface.*Thresholds<T>::getLo)();
67     auto hi = (*realIface.*Thresholds<T>::getHi)();
68     (*realIface.*Thresholds<T>::alarmLo)(value <= lo);
69     (*realIface.*Thresholds<T>::alarmHi)(value >= hi);
70 }
71 
72 /** @brief addThreshold
73  *
74  *  Look for a configured threshold value in the environment and
75  *  create an sdbusplus server threshold if found.
76  *
77  *  @tparam T - The threshold type.
78  *
79  *  @param[in] sensorType - sensor type, like 'temp'
80  *  @param[in] sensorID - sensor ID, like '5'
81  *  @param[in] value - The sensor reading.
82  *  @param[in] info - The sdbusplus server connection and interfaces.
83  */
84 template <typename T>
85 auto addThreshold(const std::string& sensorType, const std::string& sensorID,
86                   int64_t value, ObjectInfo& info, int64_t scale)
87 {
88     auto& objPath = std::get<std::string>(info);
89     auto& obj = std::get<InterfaceMap>(info);
90     std::shared_ptr<T> iface;
91 
92     auto tLo = env::getEnv(Thresholds<T>::envLo, sensorType, sensorID);
93     auto tHi = env::getEnv(Thresholds<T>::envHi, sensorType, sensorID);
94     if (!tLo.empty() && !tHi.empty())
95     {
96         static constexpr bool deferSignals = true;
97         auto& bus = *std::get<sdbusplus::bus::bus*>(info);
98 
99         iface = std::make_shared<T>(bus, objPath.c_str(), deferSignals);
100         auto lo = stod(tLo) * std::pow(10, scale);
101         auto hi = stod(tHi) * std::pow(10, scale);
102         (*iface.*Thresholds<T>::setLo)(lo);
103         (*iface.*Thresholds<T>::setHi)(hi);
104         (*iface.*Thresholds<T>::alarmLo)(value <= lo);
105         (*iface.*Thresholds<T>::alarmHi)(value >= hi);
106         auto type = Thresholds<T>::type;
107         obj[type] = iface;
108     }
109 
110     return iface;
111 }
112 
113 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
114