xref: /openbmc/phosphor-virtual-sensor/src/thresholds.hpp (revision 6272a39308bf6c1945edabf54891157c8079165a)
1 #pragma once
2 
3 #include "dbusUtils.hpp"
4 
5 #include <phosphor-logging/commit.hpp>
6 #include <xyz/openbmc_project/Sensor/Threshold/Critical/server.hpp>
7 #include <xyz/openbmc_project/Sensor/Threshold/HardShutdown/server.hpp>
8 #include <xyz/openbmc_project/Sensor/Threshold/PerformanceLoss/server.hpp>
9 #include <xyz/openbmc_project/Sensor/Threshold/SoftShutdown/server.hpp>
10 #include <xyz/openbmc_project/Sensor/Threshold/Warning/server.hpp>
11 #include <xyz/openbmc_project/Sensor/Threshold/event.hpp>
12 #include <xyz/openbmc_project/Sensor/Value/server.hpp>
13 
14 const constexpr char* entityManagerBusName =
15     "xyz.openbmc_project.EntityManager";
16 namespace phosphor::virtual_sensor
17 {
18 
19 template <typename... T>
20 using ServerObject = typename sdbusplus::server::object_t<T...>;
21 
22 namespace threshold_ns =
23     sdbusplus::xyz::openbmc_project::Sensor::Threshold::server;
24 using Unit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit;
25 using CriticalObject = ServerObject<threshold_ns::Critical>;
26 using WarningObject = ServerObject<threshold_ns::Warning>;
27 using SoftShutdownObject = ServerObject<threshold_ns::SoftShutdown>;
28 using HardShutdownObject = ServerObject<threshold_ns::HardShutdown>;
29 using PerformanceLossObject = ServerObject<threshold_ns::PerformanceLoss>;
30 
31 template <typename T>
32 struct Threshold;
33 
34 struct Hysteresis
35 {
36     double highHysteresis;
37     double lowHysteresis;
getHighHysteresisphosphor::virtual_sensor::Hysteresis38     auto getHighHysteresis()
39     {
40         return this->highHysteresis;
41     }
42 
getLowHysteresisphosphor::virtual_sensor::Hysteresis43     auto getLowHysteresis()
44     {
45         return this->lowHysteresis;
46     }
47 
setHighHysteresisphosphor::virtual_sensor::Hysteresis48     auto setHighHysteresis(double value)
49     {
50         this->highHysteresis = value;
51     }
52 
setLowHysteresisphosphor::virtual_sensor::Hysteresis53     auto setLowHysteresis(double value)
54     {
55         this->lowHysteresis = value;
56     }
57 };
58 
59 template <typename error>
tryCommit(const std::string & objPath,double value,Unit unit,double thresholdValue)60 auto tryCommit(const std::string& objPath, double value, Unit unit,
61                double thresholdValue)
62     -> std::optional<sdbusplus::message::object_path>
63 {
64     try
65     {
66         return lg2::commit(
67             error("SENSOR_NAME", objPath, "READING_VALUE", value, "UNITS", unit,
68                   "THRESHOLD_VALUE", thresholdValue));
69     }
70     catch (std::exception&)
71     {
72         lg2::error(
73             "Failed creating a threshold log entry for {SENSOR} with value {VALUE}",
74             "SENSOR", objPath, "VALUE", value);
75         return std::nullopt;
76     }
77 }
78 
tryResolve(std::optional<sdbusplus::message::object_path> & log)79 static inline void tryResolve(
80     std::optional<sdbusplus::message::object_path>& log)
81 {
82     if (log)
83     {
84         try
85         {
86             lg2::resolve(*log);
87         }
88         catch (std::exception&)
89         {
90             lg2::error("Failed to resolve: {LOG}", "LOG", *log);
91         }
92         log.reset();
93     }
94 }
95 
96 template <>
97 struct Threshold<WarningObject> : public WarningObject, public Hysteresis
98 {
99     static constexpr auto name = "Warning";
100     using WarningObject::WarningObject;
101     using ReadingAboveUpperWarningThreshold = sdbusplus::error::xyz::
102         openbmc_project::sensor::Threshold::ReadingAboveUpperWarningThreshold;
103     using ReadingBelowLowerWarningThreshold = sdbusplus::error::xyz::
104         openbmc_project::sensor::Threshold::ReadingBelowLowerWarningThreshold;
105     /** @brief sdbusplus bus client connection. */
106     sdbusplus::bus_t& bus;
107     std::string objPath;
108     Unit units;
109 
110     /** @brief Virtual sensor path/interface in entityManagerDbus.
111      * This 3 value is used to set thresholds
112      */
113     std::string entityPath;
114     std::string entityInterfaceHigh;
115     std::string entityInterfaceLow;
116     std::optional<sdbusplus::message::object_path> assertedHighLog;
117     std::optional<sdbusplus::message::object_path> assertedLowLog;
118 
119     /** @brief Constructor to put object onto bus at a dbus path.
120      *  @param[in] bus - Bus to attach to.
121      *  @param[in] path - Path to attach at.
122      *  @param[in] units - units
123      */
Thresholdphosphor::virtual_sensor::Threshold124     Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) :
125         WarningObject(bus, path), bus(bus), objPath(std::string(path)),
126         units(units)
127     {}
128 
highphosphor::virtual_sensor::Threshold129     auto high()
130     {
131         return WarningObject::warningHigh();
132     }
lowphosphor::virtual_sensor::Threshold133     auto low()
134     {
135         return WarningObject::warningLow();
136     }
137 
138     template <typename... Args>
alarmHighphosphor::virtual_sensor::Threshold139     auto alarmHigh(Args... args)
140     {
141         return warningAlarmHigh(std::forward<Args>(args)...);
142     }
143 
144     template <typename... Args>
alarmLowphosphor::virtual_sensor::Threshold145     auto alarmLow(Args... args)
146     {
147         return warningAlarmLow(std::forward<Args>(args)...);
148     }
149 
150     template <typename V>
alarmHighSignalAssertedphosphor::virtual_sensor::Threshold151     auto alarmHighSignalAsserted(V value)
152     {
153         assertedHighLog = tryCommit<ReadingAboveUpperWarningThreshold>(
154             objPath, value, units, high());
155         return warningHighAlarmAsserted(value);
156     }
157 
158     template <typename... Args>
alarmHighSignalDeassertedphosphor::virtual_sensor::Threshold159     auto alarmHighSignalDeasserted(Args... args)
160     {
161         tryResolve(assertedHighLog);
162         return warningHighAlarmDeasserted(std::forward<Args>(args)...);
163     }
164 
165     template <typename V>
alarmLowSignalAssertedphosphor::virtual_sensor::Threshold166     auto alarmLowSignalAsserted(V value)
167     {
168         assertedLowLog = tryCommit<ReadingBelowLowerWarningThreshold>(
169             objPath, value, units, low());
170         return warningLowAlarmAsserted(value);
171     }
172 
173     template <typename... Args>
alarmLowSignalDeassertedphosphor::virtual_sensor::Threshold174     auto alarmLowSignalDeasserted(Args... args)
175     {
176         tryResolve(assertedLowLog);
177         return warningLowAlarmDeasserted(std::forward<Args>(args)...);
178     }
179 
180     /** @brief Set value of WarningHigh */
warningHighphosphor::virtual_sensor::Threshold181     virtual double warningHigh(double value)
182     {
183         if (!entityPath.empty() && !entityInterfaceHigh.empty())
184         {
185             // persistThreshold
186             setDbusProperty(bus, entityManagerBusName, entityPath,
187                             entityInterfaceHigh, "Value", value);
188         }
189         return WarningObject::warningHigh(value);
190     }
191 
192     /** @brief Set value of WarningLow */
warningLowphosphor::virtual_sensor::Threshold193     virtual double warningLow(double value)
194     {
195         if (!entityPath.empty() && !entityInterfaceLow.empty())
196         {
197             // persistThreshold
198             setDbusProperty(bus, entityManagerBusName, entityPath,
199                             entityInterfaceLow, "Value", value);
200         }
201         return WarningObject::warningLow(value);
202     }
203 
204     /** @brief Set the entitymanager interface corresponding to virtualsensor
205      * warningLow
206      */
setEntityInterfaceLowphosphor::virtual_sensor::Threshold207     void setEntityInterfaceLow(const std::string& interfaceLow)
208     {
209         entityInterfaceLow = interfaceLow;
210     }
211 
212     /** @brief Set the entitymanager interface corresponding to virtualsensor
213      * warningHigh
214      */
setEntityInterfaceHighphosphor::virtual_sensor::Threshold215     void setEntityInterfaceHigh(const std::string& interfaceHigh)
216     {
217         entityInterfaceHigh = interfaceHigh;
218     }
219 
220     /** @brief Set the entitymanager path corresponding to virtualsensor warning
221      */
setEntityPathphosphor::virtual_sensor::Threshold222     void setEntityPath(const std::string& path)
223     {
224         entityPath = path;
225     }
226 };
227 
228 template <>
229 struct Threshold<CriticalObject> : public CriticalObject, public Hysteresis
230 {
231     static constexpr auto name = "Critical";
232 
233     /** @brief sdbusplus bus client connection. */
234     sdbusplus::bus_t& bus;
235     std::string objPath;
236     Unit units;
237 
238     /** @brief Virtual sensor path/interface in entityManagerDbus.
239      * This 3 value is used to set thresholds
240      */
241     std::string entityPath;
242     std::string entityInterfaceHigh;
243     std::string entityInterfaceLow;
244     std::optional<sdbusplus::message::object_path> assertedHighLog;
245     std::optional<sdbusplus::message::object_path> assertedLowLog;
246 
247     using CriticalObject::CriticalObject;
248     using ReadingAboveUpperCriticalThreshold = sdbusplus::error::xyz::
249         openbmc_project::sensor::Threshold::ReadingAboveUpperCriticalThreshold;
250     using ReadingBelowLowerCriticalThreshold = sdbusplus::error::xyz::
251         openbmc_project::sensor::Threshold::ReadingBelowLowerCriticalThreshold;
252 
253     /** @brief Constructor to put object onto bus at a dbus path.
254      *  @param[in] bus - Bus to attach to.
255      *  @param[in] path - Path to attach at.
256      *  @param[in] units - units
257      */
Thresholdphosphor::virtual_sensor::Threshold258     Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) :
259         CriticalObject(bus, path), bus(bus), objPath(std::string(path)),
260         units(units)
261     {}
262 
highphosphor::virtual_sensor::Threshold263     auto high()
264     {
265         return CriticalObject::criticalHigh();
266     }
lowphosphor::virtual_sensor::Threshold267     auto low()
268     {
269         return CriticalObject::criticalLow();
270     }
271 
272     template <typename... Args>
alarmHighphosphor::virtual_sensor::Threshold273     auto alarmHigh(Args... args)
274     {
275         return criticalAlarmHigh(std::forward<Args>(args)...);
276     }
277 
278     template <typename... Args>
alarmLowphosphor::virtual_sensor::Threshold279     auto alarmLow(Args... args)
280     {
281         return criticalAlarmLow(std::forward<Args>(args)...);
282     }
283 
284     template <typename V>
alarmHighSignalAssertedphosphor::virtual_sensor::Threshold285     auto alarmHighSignalAsserted(V value)
286     {
287         assertedHighLog = tryCommit<ReadingAboveUpperCriticalThreshold>(
288             objPath, value, units, high());
289         return criticalHighAlarmAsserted(value);
290     }
291 
292     template <typename... Args>
alarmHighSignalDeassertedphosphor::virtual_sensor::Threshold293     auto alarmHighSignalDeasserted(Args... args)
294     {
295         tryResolve(assertedHighLog);
296         return criticalHighAlarmDeasserted(std::forward<Args>(args)...);
297     }
298 
299     template <typename V>
alarmLowSignalAssertedphosphor::virtual_sensor::Threshold300     auto alarmLowSignalAsserted(V value)
301     {
302         assertedLowLog = tryCommit<ReadingBelowLowerCriticalThreshold>(
303             objPath, value, units, low());
304         return criticalLowAlarmAsserted(value);
305     }
306 
307     template <typename... Args>
alarmLowSignalDeassertedphosphor::virtual_sensor::Threshold308     auto alarmLowSignalDeasserted(Args... args)
309     {
310         tryResolve(assertedLowLog);
311         return criticalLowAlarmDeasserted(std::forward<Args>(args)...);
312     }
313 
314     /** @brief Set value of CriticalHigh */
criticalHighphosphor::virtual_sensor::Threshold315     virtual double criticalHigh(double value)
316     {
317         // persistThreshold
318         if (!entityPath.empty() && !entityInterfaceHigh.empty())
319         {
320             setDbusProperty(bus, entityManagerBusName, entityPath,
321                             entityInterfaceHigh, "Value", value);
322         }
323         return CriticalObject::criticalHigh(value);
324     }
325 
326     /** @brief Set value of CriticalLow */
criticalLowphosphor::virtual_sensor::Threshold327     virtual double criticalLow(double value)
328     {
329         if (!entityPath.empty() && !entityInterfaceLow.empty())
330         {
331             setDbusProperty(bus, entityManagerBusName, entityPath,
332                             entityInterfaceLow, "Value", value);
333         }
334         return CriticalObject::criticalLow(value);
335     }
336 
337     /** @brief Set the entitymanager interface corresponding to virtualsensor
338      * criticalLow
339      */
setEntityInterfaceLowphosphor::virtual_sensor::Threshold340     void setEntityInterfaceLow(const std::string& interfaceLow)
341     {
342         entityInterfaceLow = interfaceLow;
343     }
344 
345     /** @brief Set the entitymanager interface corresponding to virtualsensor
346      * criticalLow
347      */
setEntityInterfaceHighphosphor::virtual_sensor::Threshold348     void setEntityInterfaceHigh(const std::string& interfaceHigh)
349     {
350         entityInterfaceHigh = interfaceHigh;
351     }
352 
353     /** @brief Set the entitymanager path corresponding to virtualsensor warning
354      */
setEntityPathphosphor::virtual_sensor::Threshold355     void setEntityPath(const std::string& path)
356     {
357         entityPath = path;
358     }
359 };
360 
361 template <>
362 struct Threshold<SoftShutdownObject> :
363     public SoftShutdownObject,
364     public Hysteresis
365 {
366     static constexpr auto name = "SoftShutdown";
367 
368     /** @brief sdbusplus bus client connection. */
369     sdbusplus::bus_t& bus;
370     std::string objPath;
371     Unit units;
372 
373     using SoftShutdownObject::SoftShutdownObject;
374     using ReadingAboveUpperSoftShutdownThreshold =
375         sdbusplus::error::xyz::openbmc_project::sensor::Threshold::
376             ReadingAboveUpperSoftShutdownThreshold;
377     using ReadingBelowLowerSoftShutdownThreshold =
378         sdbusplus::error::xyz::openbmc_project::sensor::Threshold::
379             ReadingBelowLowerSoftShutdownThreshold;
380     std::optional<sdbusplus::message::object_path> assertedHighLog;
381     std::optional<sdbusplus::message::object_path> assertedLowLog;
382 
383     /** @brief Constructor to put object onto bus at a dbus path.
384      *  @param[in] bus - Bus to attach to.
385      *  @param[in] path - Path to attach at.
386      *  @param[in] units - units
387      */
Thresholdphosphor::virtual_sensor::Threshold388     Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) :
389         SoftShutdownObject(bus, path), bus(bus), objPath(std::string(path)),
390         units(units)
391     {}
392 
highphosphor::virtual_sensor::Threshold393     auto high()
394     {
395         return softShutdownHigh();
396     }
lowphosphor::virtual_sensor::Threshold397     auto low()
398     {
399         return softShutdownLow();
400     }
401 
402     template <typename... Args>
alarmHighphosphor::virtual_sensor::Threshold403     auto alarmHigh(Args... args)
404     {
405         return softShutdownAlarmHigh(std::forward<Args>(args)...);
406     }
407 
408     template <typename... Args>
alarmLowphosphor::virtual_sensor::Threshold409     auto alarmLow(Args... args)
410     {
411         return softShutdownAlarmLow(std::forward<Args>(args)...);
412     }
413 
414     template <typename V>
alarmHighSignalAssertedphosphor::virtual_sensor::Threshold415     auto alarmHighSignalAsserted(V value)
416     {
417         assertedHighLog = tryCommit<ReadingAboveUpperSoftShutdownThreshold>(
418             objPath, value, units, high());
419         return softShutdownHighAlarmAsserted(value);
420     }
421 
422     template <typename... Args>
alarmHighSignalDeassertedphosphor::virtual_sensor::Threshold423     auto alarmHighSignalDeasserted(Args... args)
424     {
425         tryResolve(assertedHighLog);
426         return softShutdownHighAlarmDeasserted(std::forward<Args>(args)...);
427     }
428 
429     template <typename V>
alarmLowSignalAssertedphosphor::virtual_sensor::Threshold430     auto alarmLowSignalAsserted(V value)
431     {
432         assertedLowLog = tryCommit<ReadingBelowLowerSoftShutdownThreshold>(
433             objPath, value, units, low());
434         return softShutdownLowAlarmAsserted(value);
435     }
436 
437     template <typename... Args>
alarmLowSignalDeassertedphosphor::virtual_sensor::Threshold438     auto alarmLowSignalDeasserted(Args... args)
439     {
440         tryResolve(assertedLowLog);
441         return softShutdownLowAlarmDeasserted(std::forward<Args>(args)...);
442     }
443 };
444 
445 template <>
446 struct Threshold<HardShutdownObject> :
447     public HardShutdownObject,
448     public Hysteresis
449 {
450     static constexpr auto name = "HardShutdown";
451 
452     /** @brief sdbusplus bus client connection. */
453     sdbusplus::bus_t& bus;
454     std::string objPath;
455     Unit units;
456 
457     using HardShutdownObject::HardShutdownObject;
458     using ReadingAboveUpperHardShutdownThreshold =
459         sdbusplus::error::xyz::openbmc_project::sensor::Threshold::
460             ReadingAboveUpperHardShutdownThreshold;
461     using ReadingBelowLowerHardShutdownThreshold =
462         sdbusplus::error::xyz::openbmc_project::sensor::Threshold::
463             ReadingBelowLowerHardShutdownThreshold;
464     std::optional<sdbusplus::message::object_path> assertedHighLog;
465     std::optional<sdbusplus::message::object_path> assertedLowLog;
466 
467     /** @brief Constructor to put object onto bus at a dbus path.
468      *  @param[in] bus - Bus to attach to.
469      *  @param[in] path - Path to attach at.
470      *  @param[in] units - units
471      */
Thresholdphosphor::virtual_sensor::Threshold472     Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) :
473         HardShutdownObject(bus, path), bus(bus), objPath(std::string(path)),
474         units(units)
475     {}
476 
highphosphor::virtual_sensor::Threshold477     auto high()
478     {
479         return hardShutdownHigh();
480     }
lowphosphor::virtual_sensor::Threshold481     auto low()
482     {
483         return hardShutdownLow();
484     }
485 
486     template <typename... Args>
alarmHighphosphor::virtual_sensor::Threshold487     auto alarmHigh(Args... args)
488     {
489         return hardShutdownAlarmHigh(std::forward<Args>(args)...);
490     }
491 
492     template <typename... Args>
alarmLowphosphor::virtual_sensor::Threshold493     auto alarmLow(Args... args)
494     {
495         return hardShutdownAlarmLow(std::forward<Args>(args)...);
496     }
497 
498     template <typename V>
alarmHighSignalAssertedphosphor::virtual_sensor::Threshold499     auto alarmHighSignalAsserted(V value)
500     {
501         assertedHighLog = tryCommit<ReadingAboveUpperHardShutdownThreshold>(
502             objPath, value, units, high());
503         return hardShutdownHighAlarmAsserted(value);
504     }
505 
506     template <typename... Args>
alarmHighSignalDeassertedphosphor::virtual_sensor::Threshold507     auto alarmHighSignalDeasserted(Args... args)
508     {
509         tryResolve(assertedHighLog);
510         return hardShutdownHighAlarmDeasserted(std::forward<Args>(args)...);
511     }
512 
513     template <typename V>
alarmLowSignalAssertedphosphor::virtual_sensor::Threshold514     auto alarmLowSignalAsserted(V value)
515     {
516         assertedLowLog = tryCommit<ReadingBelowLowerHardShutdownThreshold>(
517             objPath, value, units, low());
518         return hardShutdownLowAlarmAsserted(value);
519     }
520 
521     template <typename... Args>
alarmLowSignalDeassertedphosphor::virtual_sensor::Threshold522     auto alarmLowSignalDeasserted(Args... args)
523     {
524         tryResolve(assertedLowLog);
525         return hardShutdownLowAlarmDeasserted(std::forward<Args>(args)...);
526     }
527 };
528 
529 template <>
530 struct Threshold<PerformanceLossObject> :
531     public PerformanceLossObject,
532     public Hysteresis
533 {
534     static constexpr auto name = "PerformanceLoss";
535     /** @brief sdbusplus bus client connection. */
536     sdbusplus::bus_t& bus;
537     std::string objPath;
538     Unit units;
539 
540     using PerformanceLossObject::PerformanceLossObject;
541     using ReadingAboveUpperPerformanceLossThreshold =
542         sdbusplus::error::xyz::openbmc_project::sensor::Threshold::
543             ReadingAboveUpperPerformanceLossThreshold;
544     using ReadingBelowLowerPerformanceLossThreshold =
545         sdbusplus::error::xyz::openbmc_project::sensor::Threshold::
546             ReadingBelowLowerPerformanceLossThreshold;
547     double performanceLossHighHysteresis;
548     double performanceLossLowHysteresis;
549     std::optional<sdbusplus::message::object_path> assertedHighLog;
550     std::optional<sdbusplus::message::object_path> assertedLowLog;
551 
552     /** @brief Constructor to put object onto bus at a dbus path.
553      *  @param[in] bus - Bus to attach to.
554      *  @param[in] path - Path to attach at.
555      *  @param[in] units - units
556      */
Thresholdphosphor::virtual_sensor::Threshold557     Threshold(sdbusplus::bus_t& bus, const char* path, Unit units) :
558         PerformanceLossObject(bus, path), bus(bus), objPath(std::string(path)),
559         units(units)
560     {}
561 
highphosphor::virtual_sensor::Threshold562     auto high()
563     {
564         return performanceLossHigh();
565     }
lowphosphor::virtual_sensor::Threshold566     auto low()
567     {
568         return performanceLossLow();
569     }
570 
571     template <typename... Args>
alarmHighphosphor::virtual_sensor::Threshold572     auto alarmHigh(Args... args)
573     {
574         return performanceLossAlarmHigh(std::forward<Args>(args)...);
575     }
576 
577     template <typename... Args>
alarmLowphosphor::virtual_sensor::Threshold578     auto alarmLow(Args... args)
579     {
580         return performanceLossAlarmLow(std::forward<Args>(args)...);
581     }
582 
583     template <typename V>
alarmHighSignalAssertedphosphor::virtual_sensor::Threshold584     auto alarmHighSignalAsserted(V value)
585     {
586         assertedHighLog = tryCommit<ReadingAboveUpperPerformanceLossThreshold>(
587             objPath, value, units, high());
588         return performanceLossHighAlarmAsserted(value);
589     }
590 
591     template <typename... Args>
alarmHighSignalDeassertedphosphor::virtual_sensor::Threshold592     auto alarmHighSignalDeasserted(Args... args)
593     {
594         tryResolve(assertedHighLog);
595         return performanceLossHighAlarmDeasserted(std::forward<Args>(args)...);
596     }
597 
598     template <typename V>
alarmLowSignalAssertedphosphor::virtual_sensor::Threshold599     auto alarmLowSignalAsserted(V value)
600     {
601         assertedLowLog = tryCommit<ReadingBelowLowerPerformanceLossThreshold>(
602             objPath, value, units, low());
603         return performanceLossLowAlarmAsserted(value);
604     }
605 
606     template <typename... Args>
alarmLowSignalDeassertedphosphor::virtual_sensor::Threshold607     auto alarmLowSignalDeasserted(Args... args)
608     {
609         tryResolve(assertedLowLog);
610         return performanceLossLowAlarmDeasserted(std::forward<Args>(args)...);
611     }
612 };
613 
614 } // namespace phosphor::virtual_sensor
615