xref: /openbmc/phosphor-hwmon/thresholds.hpp (revision b6865fdcc10dbfd5ff023f3b74d9c8b645d319db)
1e228acc0SBrad Bishop #pragma once
2e228acc0SBrad Bishop 
37a5285deSPatrick Venture #include "env.hpp"
4ee73f5bdSJames Feist #include "interface.hpp"
5ee73f5bdSJames Feist 
6ee73f5bdSJames Feist #include <cmath>
77a5285deSPatrick Venture 
8e228acc0SBrad Bishop /** @class Thresholds
9e228acc0SBrad Bishop  *  @brief Threshold type traits.
10e228acc0SBrad Bishop  *
11e228acc0SBrad Bishop  *  @tparam T - The threshold type.
12e228acc0SBrad Bishop  */
13e228acc0SBrad Bishop template <typename T>
14e228acc0SBrad Bishop struct Thresholds
15e228acc0SBrad Bishop {
failThresholds16e228acc0SBrad Bishop     static void fail()
17e228acc0SBrad Bishop     {
18e228acc0SBrad Bishop         static_assert(sizeof(Thresholds) == -1, "Unsupported Threshold type");
19e228acc0SBrad Bishop     }
20e228acc0SBrad Bishop };
21e228acc0SBrad Bishop 
22e228acc0SBrad Bishop /**@brief Thresholds specialization for warning thresholds. */
23e228acc0SBrad Bishop template <>
24e228acc0SBrad Bishop struct Thresholds<WarningObject>
25e228acc0SBrad Bishop {
26e228acc0SBrad Bishop     static constexpr InterfaceType type = InterfaceType::WARN;
27e228acc0SBrad Bishop     static constexpr const char* envLo = "WARNLO";
28e228acc0SBrad Bishop     static constexpr const char* envHi = "WARNHI";
29ee73f5bdSJames Feist     static SensorValueType (WarningObject::* const setLo)(SensorValueType);
30ee73f5bdSJames Feist     static SensorValueType (WarningObject::* const setHi)(SensorValueType);
31ee73f5bdSJames Feist     static SensorValueType (WarningObject::* const getLo)() const;
32ee73f5bdSJames Feist     static SensorValueType (WarningObject::* const getHi)() const;
33973886dbSSaqib Khan     static bool (WarningObject::* const alarmLo)(bool);
34973886dbSSaqib Khan     static bool (WarningObject::* const alarmHi)(bool);
3573769099SDuke Du     static bool (WarningObject::* const getAlarmLow)() const;
3673769099SDuke Du     static bool (WarningObject::* const getAlarmHigh)() const;
3773769099SDuke Du     static void (WarningObject::* const assertLowSignal)(SensorValueType);
3873769099SDuke Du     static void (WarningObject::* const assertHighSignal)(SensorValueType);
3973769099SDuke Du     static void (WarningObject::* const deassertLowSignal)(SensorValueType);
4073769099SDuke Du     static void (WarningObject::* const deassertHighSignal)(SensorValueType);
41e228acc0SBrad Bishop };
42e228acc0SBrad Bishop 
43e228acc0SBrad Bishop /**@brief Thresholds specialization for critical thresholds. */
44e228acc0SBrad Bishop template <>
45e228acc0SBrad Bishop struct Thresholds<CriticalObject>
46e228acc0SBrad Bishop {
47e228acc0SBrad Bishop     static constexpr InterfaceType type = InterfaceType::CRIT;
48e228acc0SBrad Bishop     static constexpr const char* envLo = "CRITLO";
49e228acc0SBrad Bishop     static constexpr const char* envHi = "CRITHI";
50ee73f5bdSJames Feist     static SensorValueType (CriticalObject::* const setLo)(SensorValueType);
51ee73f5bdSJames Feist     static SensorValueType (CriticalObject::* const setHi)(SensorValueType);
52ee73f5bdSJames Feist     static SensorValueType (CriticalObject::* const getLo)() const;
53ee73f5bdSJames Feist     static SensorValueType (CriticalObject::* const getHi)() const;
54973886dbSSaqib Khan     static bool (CriticalObject::* const alarmLo)(bool);
55973886dbSSaqib Khan     static bool (CriticalObject::* const alarmHi)(bool);
5673769099SDuke Du     static bool (CriticalObject::* const getAlarmLow)() const;
5773769099SDuke Du     static bool (CriticalObject::* const getAlarmHigh)() const;
5873769099SDuke Du     static void (CriticalObject::* const assertLowSignal)(SensorValueType);
5973769099SDuke Du     static void (CriticalObject::* const assertHighSignal)(SensorValueType);
6073769099SDuke Du     static void (CriticalObject::* const deassertLowSignal)(SensorValueType);
6173769099SDuke Du     static void (CriticalObject::* const deassertHighSignal)(SensorValueType);
62e228acc0SBrad Bishop };
63e228acc0SBrad Bishop 
64e228acc0SBrad Bishop /** @brief checkThresholds
65e228acc0SBrad Bishop  *
66e228acc0SBrad Bishop  *  Compare a sensor reading to threshold values and set the
67e228acc0SBrad Bishop  *  appropriate alarm property if bounds are exceeded.
68e228acc0SBrad Bishop  *
69e228acc0SBrad Bishop  *  @tparam T - The threshold type.
70e228acc0SBrad Bishop  *
71e228acc0SBrad Bishop  *  @param[in] iface - An sdbusplus server threshold instance.
72e228acc0SBrad Bishop  *  @param[in] value - The sensor reading to compare to thresholds.
73e228acc0SBrad Bishop  */
74e228acc0SBrad Bishop template <typename T>
checkThresholds(std::any & iface,SensorValueType value)75ee73f5bdSJames Feist void checkThresholds(std::any& iface, SensorValueType value)
76e228acc0SBrad Bishop {
774cbdfef2SWilliam A. Kennington III     auto realIface = std::any_cast<std::shared_ptr<T>>(iface);
78e228acc0SBrad Bishop     auto lo = (*realIface.*Thresholds<T>::getLo)();
79e228acc0SBrad Bishop     auto hi = (*realIface.*Thresholds<T>::getHi)();
8073769099SDuke Du     auto alarmLowState = (*realIface.*Thresholds<T>::getAlarmLow)();
8173769099SDuke Du     auto alarmHighState = (*realIface.*Thresholds<T>::getAlarmHigh)();
82fe17effcSChiabing Lee     (*realIface.*Thresholds<T>::alarmLo)(value <= lo);
83fe17effcSChiabing Lee     (*realIface.*Thresholds<T>::alarmHi)(value >= hi);
8473769099SDuke Du     if (alarmLowState != (value <= lo))
8573769099SDuke Du     {
8673769099SDuke Du         if (value <= lo)
8773769099SDuke Du         {
8873769099SDuke Du             (*realIface.*Thresholds<T>::assertLowSignal)(value);
8973769099SDuke Du         }
9073769099SDuke Du         else
9173769099SDuke Du         {
9273769099SDuke Du             (*realIface.*Thresholds<T>::deassertLowSignal)(value);
9373769099SDuke Du         }
9473769099SDuke Du     }
9573769099SDuke Du     if (alarmHighState != (value >= hi))
9673769099SDuke Du     {
9773769099SDuke Du         if (value >= hi)
9873769099SDuke Du         {
9973769099SDuke Du             (*realIface.*Thresholds<T>::assertHighSignal)(value);
10073769099SDuke Du         }
10173769099SDuke Du         else
10273769099SDuke Du         {
10373769099SDuke Du             (*realIface.*Thresholds<T>::deassertHighSignal)(value);
10473769099SDuke Du         }
10573769099SDuke Du     }
106e228acc0SBrad Bishop }
107e228acc0SBrad Bishop 
108e228acc0SBrad Bishop /** @brief addThreshold
109e228acc0SBrad Bishop  *
110e228acc0SBrad Bishop  *  Look for a configured threshold value in the environment and
111e228acc0SBrad Bishop  *  create an sdbusplus server threshold if found.
112e228acc0SBrad Bishop  *
113e228acc0SBrad Bishop  *  @tparam T - The threshold type.
114e228acc0SBrad Bishop  *
115ccfc77b6SMatt Spinler  *  @param[in] sensorType - sensor type, like 'temp'
116ccfc77b6SMatt Spinler  *  @param[in] sensorID - sensor ID, like '5'
117e228acc0SBrad Bishop  *  @param[in] value - The sensor reading.
118e228acc0SBrad Bishop  *  @param[in] info - The sdbusplus server connection and interfaces.
119e228acc0SBrad Bishop  */
120e228acc0SBrad Bishop template <typename T>
addThreshold(const std::string & sensorType,const std::string & sensorID,SensorValueType value,ObjectInfo & info,int64_t scale)121043d3230SPatrick Venture auto addThreshold(const std::string& sensorType, const std::string& sensorID,
12273769099SDuke Du                   SensorValueType value, ObjectInfo& info, int64_t scale)
123e228acc0SBrad Bishop {
124e228acc0SBrad Bishop     auto& objPath = std::get<std::string>(info);
1256206723dSPatrick Venture     auto& obj = std::get<InterfaceMap>(info);
126e228acc0SBrad Bishop     std::shared_ptr<T> iface;
127ccfc77b6SMatt Spinler 
1287a5285deSPatrick Venture     auto tLo = env::getEnv(Thresholds<T>::envLo, sensorType, sensorID);
1297a5285deSPatrick Venture     auto tHi = env::getEnv(Thresholds<T>::envHi, sensorType, sensorID);
13004da0551SThang Q. Nguyen     if (!tLo.empty() || !tHi.empty())
131e228acc0SBrad Bishop     {
132*ad6043f6SPatrick Williams         auto& bus = *std::get<sdbusplus::bus_t*>(info);
133685efa16SPatrick Venture 
134d273b1e0SPatrick Williams         iface = std::make_shared<T>(bus, objPath.c_str(),
135d273b1e0SPatrick Williams                                     T::action::emit_no_signals);
13604da0551SThang Q. Nguyen         if (!tLo.empty())
13704da0551SThang Q. Nguyen         {
138ee73f5bdSJames Feist             auto lo = stod(tLo) * std::pow(10, scale);
139e228acc0SBrad Bishop             (*iface.*Thresholds<T>::setLo)(lo);
14073769099SDuke Du             auto alarmLowState = (*iface.*Thresholds<T>::getAlarmLow)();
141fe17effcSChiabing Lee             (*iface.*Thresholds<T>::alarmLo)(value <= lo);
14273769099SDuke Du             if (alarmLowState != (value <= lo))
14373769099SDuke Du             {
14473769099SDuke Du                 if (value <= lo)
14573769099SDuke Du                 {
14673769099SDuke Du                     (*iface.*Thresholds<T>::assertLowSignal)(value);
14773769099SDuke Du                 }
14873769099SDuke Du                 else
14973769099SDuke Du                 {
15073769099SDuke Du                     (*iface.*Thresholds<T>::deassertLowSignal)(value);
15173769099SDuke Du                 }
15273769099SDuke Du             }
15304da0551SThang Q. Nguyen         }
15404da0551SThang Q. Nguyen         if (!tHi.empty())
15504da0551SThang Q. Nguyen         {
15604da0551SThang Q. Nguyen             auto hi = stod(tHi) * std::pow(10, scale);
15704da0551SThang Q. Nguyen             (*iface.*Thresholds<T>::setHi)(hi);
15804da0551SThang Q. Nguyen             auto alarmHighState = (*iface.*Thresholds<T>::getAlarmHigh)();
15904da0551SThang Q. Nguyen             (*iface.*Thresholds<T>::alarmHi)(value >= hi);
16073769099SDuke Du             if (alarmHighState != (value >= hi))
16173769099SDuke Du             {
16273769099SDuke Du                 if (value >= hi)
16373769099SDuke Du                 {
16473769099SDuke Du                     (*iface.*Thresholds<T>::assertHighSignal)(value);
16573769099SDuke Du                 }
16673769099SDuke Du                 else
16773769099SDuke Du                 {
16873769099SDuke Du                     (*iface.*Thresholds<T>::deassertHighSignal)(value);
16973769099SDuke Du                 }
17073769099SDuke Du             }
17104da0551SThang Q. Nguyen         }
172e228acc0SBrad Bishop         auto type = Thresholds<T>::type;
173e228acc0SBrad Bishop         obj[type] = iface;
174e228acc0SBrad Bishop     }
175e228acc0SBrad Bishop 
176e228acc0SBrad Bishop     return iface;
177e228acc0SBrad Bishop }
178