blob: af6efad94f453c0538eb8a5e02cb51312057e57e [file] [log] [blame]
Thu Nguyen3c5486d2024-08-01 08:03:08 +00001#include "numeric_sensor.hpp"
2
3#include "libpldm/platform.h"
4
5#include "common/utils.hpp"
6#include "requester/handler.hpp"
7
8#include <limits>
9#include <regex>
10
11PHOSPHOR_LOG2_USING;
12
13namespace pldm
14{
15namespace platform_mc
16{
17
Gilbert Cheneac61a42022-02-23 20:56:19 +000018NumericSensor::NumericSensor(
19 const pldm_tid_t tid, const bool sensorDisabled,
20 std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr, std::string& sensorName,
21 std::string& associationPath) : tid(tid), sensorName(sensorName)
Thu Nguyen3c5486d2024-08-01 08:03:08 +000022{
23 if (!pdr)
24 {
25 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
26 }
27
28 sensorId = pdr->sensor_id;
29 std::string path;
30 SensorUnit sensorUnit = SensorUnit::DegreesC;
31
32 switch (pdr->base_unit)
33 {
34 case PLDM_SENSOR_UNIT_DEGRESS_C:
35 sensorNameSpace = "/xyz/openbmc_project/sensors/temperature/";
36 sensorUnit = SensorUnit::DegreesC;
37 break;
38 case PLDM_SENSOR_UNIT_VOLTS:
39 sensorNameSpace = "/xyz/openbmc_project/sensors/voltage/";
40 sensorUnit = SensorUnit::Volts;
41 break;
42 case PLDM_SENSOR_UNIT_AMPS:
43 sensorNameSpace = "/xyz/openbmc_project/sensors/current/";
44 sensorUnit = SensorUnit::Amperes;
45 break;
46 case PLDM_SENSOR_UNIT_RPM:
47 sensorNameSpace = "/xyz/openbmc_project/sensors/fan_pwm/";
48 sensorUnit = SensorUnit::RPMS;
49 break;
50 case PLDM_SENSOR_UNIT_WATTS:
51 sensorNameSpace = "/xyz/openbmc_project/sensors/power/";
52 sensorUnit = SensorUnit::Watts;
53 break;
54 case PLDM_SENSOR_UNIT_JOULES:
55 sensorNameSpace = "/xyz/openbmc_project/sensors/energy/";
56 sensorUnit = SensorUnit::Joules;
57 break;
58 case PLDM_SENSOR_UNIT_PERCENTAGE:
59 sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/";
60 sensorUnit = SensorUnit::Percent;
61 break;
62 default:
63 lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME",
64 sensorName, "UNIT", pdr->base_unit);
65 throw sdbusplus::xyz::openbmc_project::Common::Error::
66 InvalidArgument();
67 break;
68 }
69
70 path = sensorNameSpace + sensorName;
71 try
72 {
73 auto service = pldm::utils::DBusHandler().getService(
74 path.c_str(), "xyz.openbmc_project.Sensor.Value");
75 if (!service.empty())
76 {
77 throw sdbusplus::xyz::openbmc_project::Common::Error::
78 TooManyResources();
79 }
80 }
81 catch (const std::exception&)
82 {
83 /* The sensor object path is not created */
84 }
85
86 auto& bus = pldm::utils::DBusHandler::getBus();
87 try
88 {
89 associationDefinitionsIntf =
90 std::make_unique<AssociationDefinitionsInft>(bus, path.c_str());
91 }
92 catch (const sdbusplus::exception_t& e)
93 {
94 lg2::error(
95 "Failed to create association interface for numeric sensor {PATH} error - {ERROR}",
96 "PATH", path, "ERROR", e);
97 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
98 }
99
100 associationDefinitionsIntf->associations(
101 {{"chassis", "all_sensors", associationPath}});
102
103 double maxValue = std::numeric_limits<double>::quiet_NaN();
104 double minValue = std::numeric_limits<double>::quiet_NaN();
105
106 switch (pdr->sensor_data_size)
107 {
108 case PLDM_SENSOR_DATA_SIZE_UINT8:
109 maxValue = pdr->max_readable.value_u8;
110 minValue = pdr->min_readable.value_u8;
111 hysteresis = pdr->hysteresis.value_u8;
112 break;
113 case PLDM_SENSOR_DATA_SIZE_SINT8:
114 maxValue = pdr->max_readable.value_s8;
115 minValue = pdr->min_readable.value_s8;
116 hysteresis = pdr->hysteresis.value_s8;
117 break;
118 case PLDM_SENSOR_DATA_SIZE_UINT16:
119 maxValue = pdr->max_readable.value_u16;
120 minValue = pdr->min_readable.value_u16;
121 hysteresis = pdr->hysteresis.value_u16;
122 break;
123 case PLDM_SENSOR_DATA_SIZE_SINT16:
124 maxValue = pdr->max_readable.value_s16;
125 minValue = pdr->min_readable.value_s16;
126 hysteresis = pdr->hysteresis.value_s16;
127 break;
128 case PLDM_SENSOR_DATA_SIZE_UINT32:
129 maxValue = pdr->max_readable.value_u32;
130 minValue = pdr->min_readable.value_u32;
131 hysteresis = pdr->hysteresis.value_u32;
132 break;
133 case PLDM_SENSOR_DATA_SIZE_SINT32:
134 maxValue = pdr->max_readable.value_s32;
135 minValue = pdr->min_readable.value_s32;
136 hysteresis = pdr->hysteresis.value_s32;
137 break;
138 }
139
140 bool hasCriticalThresholds = false;
141 bool hasWarningThresholds = false;
142 double criticalHigh = std::numeric_limits<double>::quiet_NaN();
143 double criticalLow = std::numeric_limits<double>::quiet_NaN();
144 double warningHigh = std::numeric_limits<double>::quiet_NaN();
145 double warningLow = std::numeric_limits<double>::quiet_NaN();
146
147 if (pdr->supported_thresholds.bits.bit0)
148 {
149 hasWarningThresholds = true;
150 switch (pdr->range_field_format)
151 {
152 case PLDM_RANGE_FIELD_FORMAT_UINT8:
153 warningHigh = pdr->warning_high.value_u8;
154 break;
155 case PLDM_RANGE_FIELD_FORMAT_SINT8:
156 warningHigh = pdr->warning_high.value_s8;
157 break;
158 case PLDM_RANGE_FIELD_FORMAT_UINT16:
159 warningHigh = pdr->warning_high.value_u16;
160 break;
161 case PLDM_RANGE_FIELD_FORMAT_SINT16:
162 warningHigh = pdr->warning_high.value_s16;
163 break;
164 case PLDM_RANGE_FIELD_FORMAT_UINT32:
165 warningHigh = pdr->warning_high.value_u32;
166 break;
167 case PLDM_RANGE_FIELD_FORMAT_SINT32:
168 warningHigh = pdr->warning_high.value_s32;
169 break;
170 case PLDM_RANGE_FIELD_FORMAT_REAL32:
171 warningHigh = pdr->warning_high.value_f32;
172 break;
173 }
174 }
175
176 if (pdr->supported_thresholds.bits.bit3)
177 {
178 hasWarningThresholds = true;
179 switch (pdr->range_field_format)
180 {
181 case PLDM_RANGE_FIELD_FORMAT_UINT8:
182 warningLow = pdr->warning_low.value_u8;
183 break;
184 case PLDM_RANGE_FIELD_FORMAT_SINT8:
185 warningLow = pdr->warning_low.value_s8;
186 break;
187 case PLDM_RANGE_FIELD_FORMAT_UINT16:
188 warningLow = pdr->warning_low.value_u16;
189 break;
190 case PLDM_RANGE_FIELD_FORMAT_SINT16:
191 warningLow = pdr->warning_low.value_s16;
192 break;
193 case PLDM_RANGE_FIELD_FORMAT_UINT32:
194 warningLow = pdr->warning_low.value_u32;
195 break;
196 case PLDM_RANGE_FIELD_FORMAT_SINT32:
197 warningLow = pdr->warning_low.value_s32;
198 break;
199 case PLDM_RANGE_FIELD_FORMAT_REAL32:
200 warningLow = pdr->warning_low.value_f32;
201 break;
202 }
203 }
204
205 if (pdr->supported_thresholds.bits.bit1)
206 {
207 hasCriticalThresholds = true;
208 switch (pdr->range_field_format)
209 {
210 case PLDM_RANGE_FIELD_FORMAT_UINT8:
211 criticalHigh = pdr->critical_high.value_u8;
212 break;
213 case PLDM_RANGE_FIELD_FORMAT_SINT8:
214 criticalHigh = pdr->critical_high.value_s8;
215 break;
216 case PLDM_RANGE_FIELD_FORMAT_UINT16:
217 criticalHigh = pdr->critical_high.value_u16;
218 break;
219 case PLDM_RANGE_FIELD_FORMAT_SINT16:
220 criticalHigh = pdr->critical_high.value_s16;
221 break;
222 case PLDM_RANGE_FIELD_FORMAT_UINT32:
223 criticalHigh = pdr->critical_high.value_u32;
224 break;
225 case PLDM_RANGE_FIELD_FORMAT_SINT32:
226 criticalHigh = pdr->critical_high.value_s32;
227 break;
228 case PLDM_RANGE_FIELD_FORMAT_REAL32:
229 criticalHigh = pdr->critical_high.value_f32;
230 break;
231 }
232 }
233
234 if (pdr->supported_thresholds.bits.bit4)
235 {
236 hasCriticalThresholds = true;
237 switch (pdr->range_field_format)
238 {
239 case PLDM_RANGE_FIELD_FORMAT_UINT8:
240 criticalLow = pdr->critical_low.value_u8;
241 break;
242 case PLDM_RANGE_FIELD_FORMAT_SINT8:
243 criticalLow = pdr->critical_low.value_s8;
244 break;
245 case PLDM_RANGE_FIELD_FORMAT_UINT16:
246 criticalLow = pdr->critical_low.value_u16;
247 break;
248 case PLDM_RANGE_FIELD_FORMAT_SINT16:
249 criticalLow = pdr->critical_low.value_s16;
250 break;
251 case PLDM_RANGE_FIELD_FORMAT_UINT32:
252 criticalLow = pdr->critical_low.value_u32;
253 break;
254 case PLDM_RANGE_FIELD_FORMAT_SINT32:
255 criticalLow = pdr->critical_low.value_s32;
256 break;
257 case PLDM_RANGE_FIELD_FORMAT_REAL32:
258 criticalLow = pdr->critical_low.value_f32;
259 break;
260 }
261 }
262
263 resolution = pdr->resolution;
264 offset = pdr->offset;
265 baseUnitModifier = pdr->unit_modifier;
Gilbert Cheneac61a42022-02-23 20:56:19 +0000266 timeStamp = 0;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000267
268 /**
269 * DEFAULT_SENSOR_UPDATER_INTERVAL is in milliseconds
270 * updateTime is in microseconds
271 */
272 updateTime = static_cast<uint64_t>(DEFAULT_SENSOR_UPDATER_INTERVAL * 1000);
273 if (!std::isnan(pdr->update_interval))
274 {
275 updateTime = pdr->update_interval * 1000000;
276 }
277
278 try
279 {
280 valueIntf = std::make_unique<ValueIntf>(bus, path.c_str());
281 }
282 catch (const sdbusplus::exception_t& e)
283 {
284 lg2::error(
285 "Failed to create Value interface for numeric sensor {PATH} error - {ERROR}",
286 "PATH", path, "ERROR", e);
287 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
288 }
289 valueIntf->maxValue(unitModifier(conversionFormula(maxValue)));
290 valueIntf->minValue(unitModifier(conversionFormula(minValue)));
291 hysteresis = unitModifier(conversionFormula(hysteresis));
292 valueIntf->unit(sensorUnit);
293
294 try
295 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400296 availabilityIntf =
297 std::make_unique<AvailabilityIntf>(bus, path.c_str());
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000298 }
299 catch (const sdbusplus::exception_t& e)
300 {
301 lg2::error(
302 "Failed to create Availability interface for numeric sensor {PATH} error - {ERROR}",
303 "PATH", path, "ERROR", e);
304 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
305 }
306 availabilityIntf->available(true);
307
308 try
309 {
310 operationalStatusIntf =
311 std::make_unique<OperationalStatusIntf>(bus, path.c_str());
312 }
313 catch (const sdbusplus::exception_t& e)
314 {
315 lg2::error(
316 "Failed to create Operation status interface for numeric sensor {PATH} error - {ERROR}",
317 "PATH", path, "ERROR", e);
318 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
319 }
320 operationalStatusIntf->functional(!sensorDisabled);
321
322 if (hasWarningThresholds)
323 {
324 try
325 {
326 thresholdWarningIntf =
327 std::make_unique<ThresholdWarningIntf>(bus, path.c_str());
328 }
329 catch (const sdbusplus::exception_t& e)
330 {
331 lg2::error(
332 "Failed to create Threshold warning interface for numeric sensor {PATH} error - {ERROR}",
333 "PATH", path, "ERROR", e);
334 throw sdbusplus::xyz::openbmc_project::Common::Error::
335 InvalidArgument();
336 }
337 thresholdWarningIntf->warningHigh(unitModifier(warningHigh));
338 thresholdWarningIntf->warningLow(unitModifier(warningLow));
339 }
340
341 if (hasCriticalThresholds)
342 {
343 try
344 {
345 thresholdCriticalIntf =
346 std::make_unique<ThresholdCriticalIntf>(bus, path.c_str());
347 }
348 catch (const sdbusplus::exception_t& e)
349 {
350 lg2::error(
351 "Failed to create Threshold critical interface for numeric sensor {PATH} error - {ERROR}",
352 "PATH", path, "ERROR", e);
353 throw sdbusplus::xyz::openbmc_project::Common::Error::
354 InvalidArgument();
355 }
356 thresholdCriticalIntf->criticalHigh(unitModifier(criticalHigh));
357 thresholdCriticalIntf->criticalLow(unitModifier(criticalLow));
358 }
359}
360
361NumericSensor::NumericSensor(
362 const pldm_tid_t tid, const bool sensorDisabled,
363 std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr,
364 std::string& sensorName, std::string& associationPath) :
Gilbert Cheneac61a42022-02-23 20:56:19 +0000365 tid(tid), sensorName(sensorName)
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000366{
367 if (!pdr)
368 {
369 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
370 }
371
372 sensorId = pdr->sensor_id;
373 std::string path;
374 SensorUnit sensorUnit = SensorUnit::DegreesC;
375
376 switch (pdr->base_unit)
377 {
378 case PLDM_SENSOR_UNIT_DEGRESS_C:
379 sensorNameSpace = "/xyz/openbmc_project/sensors/temperature/";
380 sensorUnit = SensorUnit::DegreesC;
381 break;
382 case PLDM_SENSOR_UNIT_VOLTS:
383 sensorNameSpace = "/xyz/openbmc_project/sensors/voltage/";
384 sensorUnit = SensorUnit::Volts;
385 break;
386 case PLDM_SENSOR_UNIT_AMPS:
387 sensorNameSpace = "/xyz/openbmc_project/sensors/current/";
388 sensorUnit = SensorUnit::Amperes;
389 break;
390 case PLDM_SENSOR_UNIT_RPM:
391 sensorNameSpace = "/xyz/openbmc_project/sensors/fan_pwm/";
392 sensorUnit = SensorUnit::RPMS;
393 break;
394 case PLDM_SENSOR_UNIT_WATTS:
395 sensorNameSpace = "/xyz/openbmc_project/sensors/power/";
396 sensorUnit = SensorUnit::Watts;
397 break;
398 case PLDM_SENSOR_UNIT_JOULES:
399 sensorNameSpace = "/xyz/openbmc_project/sensors/energy/";
400 sensorUnit = SensorUnit::Joules;
401 break;
402 case PLDM_SENSOR_UNIT_PERCENTAGE:
403 sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/";
404 sensorUnit = SensorUnit::Percent;
405 break;
406 default:
407 lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME",
408 sensorName, "UNIT", pdr->base_unit);
409 throw sdbusplus::xyz::openbmc_project::Common::Error::
410 InvalidArgument();
411 break;
412 }
413
414 path = sensorNameSpace + sensorName;
415 try
416 {
417 auto service = pldm::utils::DBusHandler().getService(
418 path.c_str(), "xyz.openbmc_project.Sensor.Value");
419 if (!service.empty())
420 {
421 throw sdbusplus::xyz::openbmc_project::Common::Error::
422 TooManyResources();
423 }
424 }
425 catch (const std::exception&)
426 {
427 /* The sensor object path is not created */
428 }
429
430 auto& bus = pldm::utils::DBusHandler::getBus();
431 try
432 {
433 associationDefinitionsIntf =
434 std::make_unique<AssociationDefinitionsInft>(bus, path.c_str());
435 }
436 catch (const sdbusplus::exception_t& e)
437 {
438 lg2::error(
439 "Failed to create Association interface for compact numeric sensor {PATH} error - {ERROR}",
440 "PATH", path, "ERROR", e);
441 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
442 }
443 associationDefinitionsIntf->associations(
444 {{"chassis", "all_sensors", associationPath.c_str()}});
445
446 double maxValue = std::numeric_limits<double>::quiet_NaN();
447 double minValue = std::numeric_limits<double>::quiet_NaN();
448 bool hasWarningThresholds = false;
449 bool hasCriticalThresholds = false;
450 double criticalHigh = std::numeric_limits<double>::quiet_NaN();
451 double criticalLow = std::numeric_limits<double>::quiet_NaN();
452 double warningHigh = std::numeric_limits<double>::quiet_NaN();
453 double warningLow = std::numeric_limits<double>::quiet_NaN();
454
455 if (pdr->range_field_support.bits.bit0)
456 {
457 hasWarningThresholds = true;
458 warningHigh = pdr->warning_high;
459 }
460 if (pdr->range_field_support.bits.bit1)
461 {
462 hasWarningThresholds = true;
463 warningLow = pdr->warning_low;
464 }
465
466 if (pdr->range_field_support.bits.bit2)
467 {
468 hasCriticalThresholds = true;
469 criticalHigh = pdr->critical_high;
470 }
471
472 if (pdr->range_field_support.bits.bit3)
473 {
474 hasCriticalThresholds = true;
475 criticalLow = pdr->critical_low;
476 }
477
478 resolution = std::numeric_limits<double>::quiet_NaN();
479 offset = std::numeric_limits<double>::quiet_NaN();
480 baseUnitModifier = pdr->unit_modifier;
Gilbert Cheneac61a42022-02-23 20:56:19 +0000481 timeStamp = 0;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000482
483 /**
484 * DEFAULT_SENSOR_UPDATER_INTERVAL is in milliseconds
485 * updateTime is in microseconds
486 */
487 updateTime = static_cast<uint64_t>(DEFAULT_SENSOR_UPDATER_INTERVAL * 1000);
488 try
489 {
490 valueIntf = std::make_unique<ValueIntf>(bus, path.c_str());
491 }
492 catch (const sdbusplus::exception_t& e)
493 {
494 lg2::error(
495 "Failed to create Value interface for compact numeric sensor {PATH} error - {ERROR}",
496 "PATH", path, "ERROR", e);
497 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
498 }
499 valueIntf->maxValue(unitModifier(conversionFormula(maxValue)));
500 valueIntf->minValue(unitModifier(conversionFormula(minValue)));
501 hysteresis = unitModifier(conversionFormula(hysteresis));
502 valueIntf->unit(sensorUnit);
503
504 try
505 {
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400506 availabilityIntf =
507 std::make_unique<AvailabilityIntf>(bus, path.c_str());
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000508 }
509 catch (const sdbusplus::exception_t& e)
510 {
511 lg2::error(
512 "Failed to create Availability interface for compact numeric sensor {PATH} error - {ERROR}",
513 "PATH", path, "ERROR", e);
514 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
515 }
516 availabilityIntf->available(true);
517
518 try
519 {
520 operationalStatusIntf =
521 std::make_unique<OperationalStatusIntf>(bus, path.c_str());
522 }
523 catch (const sdbusplus::exception_t& e)
524 {
525 lg2::error(
526 "Failed to create Operational status interface for compact numeric sensor {PATH} error - {ERROR}",
527 "PATH", path, "ERROR", e);
528 throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
529 }
530 operationalStatusIntf->functional(!sensorDisabled);
531
532 if (hasWarningThresholds)
533 {
534 try
535 {
536 thresholdWarningIntf =
537 std::make_unique<ThresholdWarningIntf>(bus, path.c_str());
538 }
539 catch (const sdbusplus::exception_t& e)
540 {
541 lg2::error(
542 "Failed to create Warning threshold interface for compact numeric sensor {PATH} error - {ERROR}",
543 "PATH", path, "ERROR", e);
544 throw sdbusplus::xyz::openbmc_project::Common::Error::
545 InvalidArgument();
546 }
547 thresholdWarningIntf->warningHigh(unitModifier(warningHigh));
548 thresholdWarningIntf->warningLow(unitModifier(warningLow));
549 }
550
551 if (hasCriticalThresholds)
552 {
553 try
554 {
555 thresholdCriticalIntf =
556 std::make_unique<ThresholdCriticalIntf>(bus, path.c_str());
557 }
558 catch (const sdbusplus::exception_t& e)
559 {
560 lg2::error(
561 "Failed to create Critical threshold interface for compact numeric sensor {PATH} error - {ERROR}",
562 "PATH", path, "ERROR", e);
563 throw sdbusplus::xyz::openbmc_project::Common::Error::
564 InvalidArgument();
565 }
566 thresholdCriticalIntf->criticalHigh(unitModifier(criticalHigh));
567 thresholdCriticalIntf->criticalLow(unitModifier(criticalLow));
568 }
569}
570
571double NumericSensor::conversionFormula(double value)
572{
573 double convertedValue = value;
574 convertedValue *= std::isnan(resolution) ? 1 : resolution;
575 convertedValue += std::isnan(offset) ? 0 : offset;
576 return convertedValue;
577}
578
579double NumericSensor::unitModifier(double value)
580{
581 return std::isnan(value) ? value : value * std::pow(10, baseUnitModifier);
582}
Gilbert Cheneac61a42022-02-23 20:56:19 +0000583
584void NumericSensor::updateReading(bool available, bool functional, double value)
585{
586 if (!availabilityIntf || !operationalStatusIntf || !valueIntf)
587 {
588 lg2::error(
589 "Failed to update sensor {NAME} D-Bus interface don't exist.",
590 "NAME", sensorName);
591 return;
592 }
593 availabilityIntf->available(available);
594 operationalStatusIntf->functional(functional);
595 double curValue = valueIntf->value();
596 double newValue = std::numeric_limits<double>::quiet_NaN();
597 if (functional && available)
598 {
599 newValue = unitModifier(conversionFormula(value));
600 if (newValue != curValue &&
601 (!std::isnan(newValue) || !std::isnan(curValue)))
602 {
603 valueIntf->value(newValue);
604 updateThresholds();
605 }
606 }
607 else
608 {
609 if (newValue != curValue &&
610 (!std::isnan(newValue) || !std::isnan(curValue)))
611 {
612 valueIntf->value(std::numeric_limits<double>::quiet_NaN());
613 }
614 }
615}
616
617void NumericSensor::handleErrGetSensorReading()
618{
619 if (!operationalStatusIntf || !valueIntf)
620 {
621 lg2::error(
622 "Failed to update sensor {NAME} D-Bus interfaces don't exist.",
623 "NAME", sensorName);
624 return;
625 }
626 operationalStatusIntf->functional(false);
627 valueIntf->value(std::numeric_limits<double>::quiet_NaN());
628}
629
630bool NumericSensor::checkThreshold(bool alarm, bool direction, double value,
631 double threshold, double hyst)
632{
633 if (direction)
634 {
635 if (value >= threshold)
636 {
637 return true;
638 }
639 if (value < (threshold - hyst))
640 {
641 return false;
642 }
643 }
644 else
645 {
646 if (value <= threshold)
647 {
648 return true;
649 }
650 if (value > (threshold + hyst))
651 {
652 return false;
653 }
654 }
655 return alarm;
656}
657
658void NumericSensor::updateThresholds()
659{
660 if (!valueIntf)
661 {
662 lg2::error(
663 "Failed to update thresholds sensor {NAME} D-Bus interfaces don't exist.",
664 "NAME", sensorName);
665 return;
666 }
667
668 auto value = valueIntf->value();
669
670 if (thresholdWarningIntf &&
671 !std::isnan(thresholdWarningIntf->warningHigh()))
672 {
673 auto threshold = thresholdWarningIntf->warningHigh();
674 auto alarm = thresholdWarningIntf->warningAlarmHigh();
675 auto newAlarm =
676 checkThreshold(alarm, true, value, threshold, hysteresis);
677 if (alarm != newAlarm)
678 {
679 thresholdWarningIntf->warningAlarmHigh(newAlarm);
680 if (newAlarm)
681 {
682 thresholdWarningIntf->warningHighAlarmAsserted(value);
683 }
684 else
685 {
686 thresholdWarningIntf->warningHighAlarmDeasserted(value);
687 }
688 }
689 }
690
691 if (thresholdWarningIntf && !std::isnan(thresholdWarningIntf->warningLow()))
692 {
693 auto threshold = thresholdWarningIntf->warningLow();
694 auto alarm = thresholdWarningIntf->warningAlarmLow();
695 auto newAlarm =
696 checkThreshold(alarm, false, value, threshold, hysteresis);
697 if (alarm != newAlarm)
698 {
699 thresholdWarningIntf->warningAlarmLow(newAlarm);
700 if (newAlarm)
701 {
702 thresholdWarningIntf->warningLowAlarmAsserted(value);
703 }
704 else
705 {
706 thresholdWarningIntf->warningLowAlarmDeasserted(value);
707 }
708 }
709 }
710
711 if (thresholdCriticalIntf &&
712 !std::isnan(thresholdCriticalIntf->criticalHigh()))
713 {
714 auto threshold = thresholdCriticalIntf->criticalHigh();
715 auto alarm = thresholdCriticalIntf->criticalAlarmHigh();
716 auto newAlarm =
717 checkThreshold(alarm, true, value, threshold, hysteresis);
718 if (alarm != newAlarm)
719 {
720 thresholdCriticalIntf->criticalAlarmHigh(newAlarm);
721 if (newAlarm)
722 {
723 thresholdCriticalIntf->criticalHighAlarmAsserted(value);
724 }
725 else
726 {
727 thresholdCriticalIntf->criticalHighAlarmDeasserted(value);
728 }
729 }
730 }
731
732 if (thresholdCriticalIntf &&
733 !std::isnan(thresholdCriticalIntf->criticalLow()))
734 {
735 auto threshold = thresholdCriticalIntf->criticalLow();
736 auto alarm = thresholdCriticalIntf->criticalAlarmLow();
737 auto newAlarm =
738 checkThreshold(alarm, false, value, threshold, hysteresis);
739 if (alarm != newAlarm)
740 {
741 thresholdCriticalIntf->criticalAlarmLow(newAlarm);
742 if (newAlarm)
743 {
744 thresholdCriticalIntf->criticalLowAlarmAsserted(value);
745 }
746 else
747 {
748 thresholdCriticalIntf->criticalLowAlarmDeasserted(value);
749 }
750 }
751 }
752}
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000753} // namespace platform_mc
754} // namespace pldm