blob: ef9d481c21bd68c4c1a26d3945833acab0fa5f32 [file] [log] [blame]
Brad Bishope228acc2017-01-06 15:29:35 -05001#pragma once
2
Patrick Venture7a5285d2018-04-17 19:15:05 -07003#include "env.hpp"
James Feistee73f5b2018-08-01 16:31:42 -07004#include "interface.hpp"
5
6#include <cmath>
Patrick Venture7a5285d2018-04-17 19:15:05 -07007
Brad Bishope228acc2017-01-06 15:29:35 -05008/** @class Thresholds
9 * @brief Threshold type traits.
10 *
11 * @tparam T - The threshold type.
12 */
13template <typename T>
14struct 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. */
23template <>
24struct Thresholds<WarningObject>
25{
26 static constexpr InterfaceType type = InterfaceType::WARN;
27 static constexpr const char* envLo = "WARNLO";
28 static constexpr const char* envHi = "WARNHI";
Patrick Williamse96daf62024-12-18 11:21:56 -050029 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);
Brad Bishope228acc2017-01-06 15:29:35 -050041};
42
43/**@brief Thresholds specialization for critical thresholds. */
44template <>
45struct Thresholds<CriticalObject>
46{
47 static constexpr InterfaceType type = InterfaceType::CRIT;
48 static constexpr const char* envLo = "CRITLO";
49 static constexpr const char* envHi = "CRITHI";
Patrick Williamse96daf62024-12-18 11:21:56 -050050 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);
Brad Bishope228acc2017-01-06 15:29:35 -050062};
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 */
74template <typename T>
James Feistee73f5b2018-08-01 16:31:42 -070075void checkThresholds(std::any& iface, SensorValueType value)
Brad Bishope228acc2017-01-06 15:29:35 -050076{
William A. Kennington III4cbdfef2018-10-18 19:19:51 -070077 auto realIface = std::any_cast<std::shared_ptr<T>>(iface);
Brad Bishope228acc2017-01-06 15:29:35 -050078 auto lo = (*realIface.*Thresholds<T>::getLo)();
79 auto hi = (*realIface.*Thresholds<T>::getHi)();
Duke Du73769092021-04-14 15:35:21 +080080 auto alarmLowState = (*realIface.*Thresholds<T>::getAlarmLow)();
81 auto alarmHighState = (*realIface.*Thresholds<T>::getAlarmHigh)();
Chiabing Leefe17eff2017-10-30 10:51:00 +080082 (*realIface.*Thresholds<T>::alarmLo)(value <= lo);
83 (*realIface.*Thresholds<T>::alarmHi)(value >= hi);
Duke Du73769092021-04-14 15:35:21 +080084 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 }
Brad Bishope228acc2017-01-06 15:29:35 -0500106}
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 *
Matt Spinlerccfc77b2017-10-12 16:49:24 -0500115 * @param[in] sensorType - sensor type, like 'temp'
116 * @param[in] sensorID - sensor ID, like '5'
Brad Bishope228acc2017-01-06 15:29:35 -0500117 * @param[in] value - The sensor reading.
118 * @param[in] info - The sdbusplus server connection and interfaces.
119 */
120template <typename T>
Patrick Venture043d3232018-08-31 10:10:53 -0700121auto addThreshold(const std::string& sensorType, const std::string& sensorID,
Duke Du73769092021-04-14 15:35:21 +0800122 SensorValueType value, ObjectInfo& info, int64_t scale)
Brad Bishope228acc2017-01-06 15:29:35 -0500123{
Brad Bishope228acc2017-01-06 15:29:35 -0500124 auto& objPath = std::get<std::string>(info);
Patrick Venture62067232019-06-19 17:39:33 -0700125 auto& obj = std::get<InterfaceMap>(info);
Brad Bishope228acc2017-01-06 15:29:35 -0500126 std::shared_ptr<T> iface;
Matt Spinlerccfc77b2017-10-12 16:49:24 -0500127
Patrick Venture7a5285d2018-04-17 19:15:05 -0700128 auto tLo = env::getEnv(Thresholds<T>::envLo, sensorType, sensorID);
129 auto tHi = env::getEnv(Thresholds<T>::envHi, sensorType, sensorID);
Thang Q. Nguyen04da0552021-07-19 04:24:31 +0000130 if (!tLo.empty() || !tHi.empty())
Brad Bishope228acc2017-01-06 15:29:35 -0500131 {
Patrick Williamsad6043f2022-07-22 19:26:56 -0500132 auto& bus = *std::get<sdbusplus::bus_t*>(info);
Patrick Venture685efa12018-10-12 18:00:13 -0700133
Patrick Williamsd273b1e2022-03-30 21:55:44 -0500134 iface = std::make_shared<T>(bus, objPath.c_str(),
135 T::action::emit_no_signals);
Thang Q. Nguyen04da0552021-07-19 04:24:31 +0000136 if (!tLo.empty())
Duke Du73769092021-04-14 15:35:21 +0800137 {
Thang Q. Nguyen04da0552021-07-19 04:24:31 +0000138 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))
Duke Du73769092021-04-14 15:35:21 +0800143 {
Thang Q. Nguyen04da0552021-07-19 04:24:31 +0000144 if (value <= lo)
145 {
146 (*iface.*Thresholds<T>::assertLowSignal)(value);
147 }
148 else
149 {
150 (*iface.*Thresholds<T>::deassertLowSignal)(value);
151 }
Duke Du73769092021-04-14 15:35:21 +0800152 }
153 }
Thang Q. Nguyen04da0552021-07-19 04:24:31 +0000154 if (!tHi.empty())
Duke Du73769092021-04-14 15:35:21 +0800155 {
Thang Q. Nguyen04da0552021-07-19 04:24:31 +0000156 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))
Duke Du73769092021-04-14 15:35:21 +0800161 {
Thang Q. Nguyen04da0552021-07-19 04:24:31 +0000162 if (value >= hi)
163 {
164 (*iface.*Thresholds<T>::assertHighSignal)(value);
165 }
166 else
167 {
168 (*iface.*Thresholds<T>::deassertHighSignal)(value);
169 }
Duke Du73769092021-04-14 15:35:21 +0800170 }
171 }
Brad Bishope228acc2017-01-06 15:29:35 -0500172 auto type = Thresholds<T>::type;
173 obj[type] = iface;
174 }
175
176 return iface;
177}