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