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 static constexpr bool deferSignals = true; 133 auto& bus = *std::get<sdbusplus::bus::bus*>(info); 134 135 iface = std::make_shared<T>(bus, objPath.c_str(), deferSignals); 136 auto lo = stod(tLo) * std::pow(10, scale); 137 auto hi = stod(tHi) * std::pow(10, scale); 138 (*iface.*Thresholds<T>::setLo)(lo); 139 (*iface.*Thresholds<T>::setHi)(hi); 140 auto alarmLowState = (*iface.*Thresholds<T>::getAlarmLow)(); 141 auto alarmHighState = (*iface.*Thresholds<T>::getAlarmHigh)(); 142 (*iface.*Thresholds<T>::alarmLo)(value <= lo); 143 (*iface.*Thresholds<T>::alarmHi)(value >= hi); 144 if (alarmLowState != (value <= lo)) 145 { 146 if (value <= lo) 147 { 148 (*iface.*Thresholds<T>::assertLowSignal)(value); 149 } 150 else 151 { 152 (*iface.*Thresholds<T>::deassertLowSignal)(value); 153 } 154 } 155 if (alarmHighState != (value >= hi)) 156 { 157 if (value >= hi) 158 { 159 (*iface.*Thresholds<T>::assertHighSignal)(value); 160 } 161 else 162 { 163 (*iface.*Thresholds<T>::deassertHighSignal)(value); 164 } 165 } 166 auto type = Thresholds<T>::type; 167 obj[type] = iface; 168 } 169 170 return iface; 171 } 172 173 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4 174