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 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> 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> 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::bus*>(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