1 #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 11 PHOSPHOR_LOG2_USING; 12 13 namespace pldm 14 { 15 namespace platform_mc 16 { 17 18 NumericSensor::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) 22 { 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; 266 timeStamp = 0; 267 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 { 296 availabilityIntf = 297 std::make_unique<AvailabilityIntf>(bus, path.c_str()); 298 } 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 361 NumericSensor::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) : 365 tid(tid), sensorName(sensorName) 366 { 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; 481 timeStamp = 0; 482 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 { 506 availabilityIntf = 507 std::make_unique<AvailabilityIntf>(bus, path.c_str()); 508 } 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 571 double 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 579 double NumericSensor::unitModifier(double value) 580 { 581 return std::isnan(value) ? value : value * std::pow(10, baseUnitModifier); 582 } 583 584 void 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 617 void 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 630 bool 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 658 void 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 } 753 } // namespace platform_mc 754 } // namespace pldm 755