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 {
failThresholds16 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 static bool (WarningObject::*const getAlarmLow)() const;
36 static bool (WarningObject::*const getAlarmHigh)() const;
37 static void (WarningObject::*const assertLowSignal)(SensorValueType);
38 static void (WarningObject::*const assertHighSignal)(SensorValueType);
39 static void (WarningObject::*const deassertLowSignal)(SensorValueType);
40 static void (WarningObject::*const deassertHighSignal)(SensorValueType);
41 };
42
43 /**@brief Thresholds specialization for critical thresholds. */
44 template <>
45 struct Thresholds<CriticalObject>
46 {
47 static constexpr InterfaceType type = InterfaceType::CRIT;
48 static constexpr const char* envLo = "CRITLO";
49 static constexpr const char* envHi = "CRITHI";
50 static SensorValueType (CriticalObject::*const setLo)(SensorValueType);
51 static SensorValueType (CriticalObject::*const setHi)(SensorValueType);
52 static SensorValueType (CriticalObject::*const getLo)() const;
53 static SensorValueType (CriticalObject::*const getHi)() const;
54 static bool (CriticalObject::*const alarmLo)(bool);
55 static bool (CriticalObject::*const alarmHi)(bool);
56 static bool (CriticalObject::*const getAlarmLow)() const;
57 static bool (CriticalObject::*const getAlarmHigh)() const;
58 static void (CriticalObject::*const assertLowSignal)(SensorValueType);
59 static void (CriticalObject::*const assertHighSignal)(SensorValueType);
60 static void (CriticalObject::*const deassertLowSignal)(SensorValueType);
61 static void (CriticalObject::*const deassertHighSignal)(SensorValueType);
62 };
63
64 /** @brief checkThresholds
65 *
66 * Compare a sensor reading to threshold values and set the
67 * appropriate alarm property if bounds are exceeded.
68 *
69 * @tparam T - The threshold type.
70 *
71 * @param[in] iface - An sdbusplus server threshold instance.
72 * @param[in] value - The sensor reading to compare to thresholds.
73 */
74 template <typename T>
checkThresholds(std::any & iface,SensorValueType value)75 void checkThresholds(std::any& iface, SensorValueType value)
76 {
77 auto realIface = std::any_cast<std::shared_ptr<T>>(iface);
78 auto lo = (*realIface.*Thresholds<T>::getLo)();
79 auto hi = (*realIface.*Thresholds<T>::getHi)();
80 auto alarmLowState = (*realIface.*Thresholds<T>::getAlarmLow)();
81 auto alarmHighState = (*realIface.*Thresholds<T>::getAlarmHigh)();
82 (*realIface.*Thresholds<T>::alarmLo)(value <= lo);
83 (*realIface.*Thresholds<T>::alarmHi)(value >= hi);
84 if (alarmLowState != (value <= lo))
85 {
86 if (value <= lo)
87 {
88 (*realIface.*Thresholds<T>::assertLowSignal)(value);
89 }
90 else
91 {
92 (*realIface.*Thresholds<T>::deassertLowSignal)(value);
93 }
94 }
95 if (alarmHighState != (value >= hi))
96 {
97 if (value >= hi)
98 {
99 (*realIface.*Thresholds<T>::assertHighSignal)(value);
100 }
101 else
102 {
103 (*realIface.*Thresholds<T>::deassertHighSignal)(value);
104 }
105 }
106 }
107
108 /** @brief addThreshold
109 *
110 * Look for a configured threshold value in the environment and
111 * create an sdbusplus server threshold if found.
112 *
113 * @tparam T - The threshold type.
114 *
115 * @param[in] sensorType - sensor type, like 'temp'
116 * @param[in] sensorID - sensor ID, like '5'
117 * @param[in] value - The sensor reading.
118 * @param[in] info - The sdbusplus server connection and interfaces.
119 */
120 template <typename T>
addThreshold(const std::string & sensorType,const std::string & sensorID,SensorValueType value,ObjectInfo & info,int64_t scale)121 auto addThreshold(const std::string& sensorType, const std::string& sensorID,
122 SensorValueType value, ObjectInfo& info, int64_t scale)
123 {
124 auto& objPath = std::get<std::string>(info);
125 auto& obj = std::get<InterfaceMap>(info);
126 std::shared_ptr<T> iface;
127
128 auto tLo = env::getEnv(Thresholds<T>::envLo, sensorType, sensorID);
129 auto tHi = env::getEnv(Thresholds<T>::envHi, sensorType, sensorID);
130 if (!tLo.empty() || !tHi.empty())
131 {
132 auto& bus = *std::get<sdbusplus::bus_t*>(info);
133
134 iface = std::make_shared<T>(bus, objPath.c_str(),
135 T::action::emit_no_signals);
136 if (!tLo.empty())
137 {
138 auto lo = stod(tLo) * std::pow(10, scale);
139 (*iface.*Thresholds<T>::setLo)(lo);
140 auto alarmLowState = (*iface.*Thresholds<T>::getAlarmLow)();
141 (*iface.*Thresholds<T>::alarmLo)(value <= lo);
142 if (alarmLowState != (value <= lo))
143 {
144 if (value <= lo)
145 {
146 (*iface.*Thresholds<T>::assertLowSignal)(value);
147 }
148 else
149 {
150 (*iface.*Thresholds<T>::deassertLowSignal)(value);
151 }
152 }
153 }
154 if (!tHi.empty())
155 {
156 auto hi = stod(tHi) * std::pow(10, scale);
157 (*iface.*Thresholds<T>::setHi)(hi);
158 auto alarmHighState = (*iface.*Thresholds<T>::getAlarmHigh)();
159 (*iface.*Thresholds<T>::alarmHi)(value >= hi);
160 if (alarmHighState != (value >= hi))
161 {
162 if (value >= hi)
163 {
164 (*iface.*Thresholds<T>::assertHighSignal)(value);
165 }
166 else
167 {
168 (*iface.*Thresholds<T>::deassertHighSignal)(value);
169 }
170 }
171 }
172 auto type = Thresholds<T>::type;
173 obj[type] = iface;
174 }
175
176 return iface;
177 }
178
179 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
180