13c5486d4SThu Nguyen #include "numeric_sensor.hpp"
23c5486d4SThu Nguyen 
33c5486d4SThu Nguyen #include "libpldm/platform.h"
43c5486d4SThu Nguyen 
53c5486d4SThu Nguyen #include "common/utils.hpp"
63c5486d4SThu Nguyen #include "requester/handler.hpp"
73c5486d4SThu Nguyen 
83c5486d4SThu Nguyen #include <limits>
93c5486d4SThu Nguyen #include <regex>
103c5486d4SThu Nguyen 
113c5486d4SThu Nguyen PHOSPHOR_LOG2_USING;
123c5486d4SThu Nguyen 
133c5486d4SThu Nguyen namespace pldm
143c5486d4SThu Nguyen {
153c5486d4SThu Nguyen namespace platform_mc
163c5486d4SThu Nguyen {
173c5486d4SThu Nguyen 
NumericSensor(const pldm_tid_t tid,const bool sensorDisabled,std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr,std::string & sensorName,std::string & associationPath)18*eac61a4bSGilbert Chen NumericSensor::NumericSensor(
19*eac61a4bSGilbert Chen     const pldm_tid_t tid, const bool sensorDisabled,
20*eac61a4bSGilbert Chen     std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr, std::string& sensorName,
21*eac61a4bSGilbert Chen     std::string& associationPath) : tid(tid), sensorName(sensorName)
223c5486d4SThu Nguyen {
233c5486d4SThu Nguyen     if (!pdr)
243c5486d4SThu Nguyen     {
253c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
263c5486d4SThu Nguyen     }
273c5486d4SThu Nguyen 
283c5486d4SThu Nguyen     sensorId = pdr->sensor_id;
293c5486d4SThu Nguyen     std::string path;
303c5486d4SThu Nguyen     SensorUnit sensorUnit = SensorUnit::DegreesC;
313c5486d4SThu Nguyen 
323c5486d4SThu Nguyen     switch (pdr->base_unit)
333c5486d4SThu Nguyen     {
343c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_DEGRESS_C:
353c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/temperature/";
363c5486d4SThu Nguyen             sensorUnit = SensorUnit::DegreesC;
373c5486d4SThu Nguyen             break;
383c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_VOLTS:
393c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/voltage/";
403c5486d4SThu Nguyen             sensorUnit = SensorUnit::Volts;
413c5486d4SThu Nguyen             break;
423c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_AMPS:
433c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/current/";
443c5486d4SThu Nguyen             sensorUnit = SensorUnit::Amperes;
453c5486d4SThu Nguyen             break;
463c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_RPM:
473c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/fan_pwm/";
483c5486d4SThu Nguyen             sensorUnit = SensorUnit::RPMS;
493c5486d4SThu Nguyen             break;
503c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_WATTS:
513c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/power/";
523c5486d4SThu Nguyen             sensorUnit = SensorUnit::Watts;
533c5486d4SThu Nguyen             break;
543c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_JOULES:
553c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/energy/";
563c5486d4SThu Nguyen             sensorUnit = SensorUnit::Joules;
573c5486d4SThu Nguyen             break;
583c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_PERCENTAGE:
593c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/";
603c5486d4SThu Nguyen             sensorUnit = SensorUnit::Percent;
613c5486d4SThu Nguyen             break;
623c5486d4SThu Nguyen         default:
633c5486d4SThu Nguyen             lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME",
643c5486d4SThu Nguyen                        sensorName, "UNIT", pdr->base_unit);
653c5486d4SThu Nguyen             throw sdbusplus::xyz::openbmc_project::Common::Error::
663c5486d4SThu Nguyen                 InvalidArgument();
673c5486d4SThu Nguyen             break;
683c5486d4SThu Nguyen     }
693c5486d4SThu Nguyen 
703c5486d4SThu Nguyen     path = sensorNameSpace + sensorName;
713c5486d4SThu Nguyen     try
723c5486d4SThu Nguyen     {
733c5486d4SThu Nguyen         auto service = pldm::utils::DBusHandler().getService(
743c5486d4SThu Nguyen             path.c_str(), "xyz.openbmc_project.Sensor.Value");
753c5486d4SThu Nguyen         if (!service.empty())
763c5486d4SThu Nguyen         {
773c5486d4SThu Nguyen             throw sdbusplus::xyz::openbmc_project::Common::Error::
783c5486d4SThu Nguyen                 TooManyResources();
793c5486d4SThu Nguyen         }
803c5486d4SThu Nguyen     }
813c5486d4SThu Nguyen     catch (const std::exception&)
823c5486d4SThu Nguyen     {
833c5486d4SThu Nguyen         /* The sensor object path is not created */
843c5486d4SThu Nguyen     }
853c5486d4SThu Nguyen 
863c5486d4SThu Nguyen     auto& bus = pldm::utils::DBusHandler::getBus();
873c5486d4SThu Nguyen     try
883c5486d4SThu Nguyen     {
893c5486d4SThu Nguyen         associationDefinitionsIntf =
903c5486d4SThu Nguyen             std::make_unique<AssociationDefinitionsInft>(bus, path.c_str());
913c5486d4SThu Nguyen     }
923c5486d4SThu Nguyen     catch (const sdbusplus::exception_t& e)
933c5486d4SThu Nguyen     {
943c5486d4SThu Nguyen         lg2::error(
953c5486d4SThu Nguyen             "Failed to create association interface for numeric sensor {PATH} error - {ERROR}",
963c5486d4SThu Nguyen             "PATH", path, "ERROR", e);
973c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
983c5486d4SThu Nguyen     }
993c5486d4SThu Nguyen 
1003c5486d4SThu Nguyen     associationDefinitionsIntf->associations(
1013c5486d4SThu Nguyen         {{"chassis", "all_sensors", associationPath}});
1023c5486d4SThu Nguyen 
1033c5486d4SThu Nguyen     double maxValue = std::numeric_limits<double>::quiet_NaN();
1043c5486d4SThu Nguyen     double minValue = std::numeric_limits<double>::quiet_NaN();
1053c5486d4SThu Nguyen 
1063c5486d4SThu Nguyen     switch (pdr->sensor_data_size)
1073c5486d4SThu Nguyen     {
1083c5486d4SThu Nguyen         case PLDM_SENSOR_DATA_SIZE_UINT8:
1093c5486d4SThu Nguyen             maxValue = pdr->max_readable.value_u8;
1103c5486d4SThu Nguyen             minValue = pdr->min_readable.value_u8;
1113c5486d4SThu Nguyen             hysteresis = pdr->hysteresis.value_u8;
1123c5486d4SThu Nguyen             break;
1133c5486d4SThu Nguyen         case PLDM_SENSOR_DATA_SIZE_SINT8:
1143c5486d4SThu Nguyen             maxValue = pdr->max_readable.value_s8;
1153c5486d4SThu Nguyen             minValue = pdr->min_readable.value_s8;
1163c5486d4SThu Nguyen             hysteresis = pdr->hysteresis.value_s8;
1173c5486d4SThu Nguyen             break;
1183c5486d4SThu Nguyen         case PLDM_SENSOR_DATA_SIZE_UINT16:
1193c5486d4SThu Nguyen             maxValue = pdr->max_readable.value_u16;
1203c5486d4SThu Nguyen             minValue = pdr->min_readable.value_u16;
1213c5486d4SThu Nguyen             hysteresis = pdr->hysteresis.value_u16;
1223c5486d4SThu Nguyen             break;
1233c5486d4SThu Nguyen         case PLDM_SENSOR_DATA_SIZE_SINT16:
1243c5486d4SThu Nguyen             maxValue = pdr->max_readable.value_s16;
1253c5486d4SThu Nguyen             minValue = pdr->min_readable.value_s16;
1263c5486d4SThu Nguyen             hysteresis = pdr->hysteresis.value_s16;
1273c5486d4SThu Nguyen             break;
1283c5486d4SThu Nguyen         case PLDM_SENSOR_DATA_SIZE_UINT32:
1293c5486d4SThu Nguyen             maxValue = pdr->max_readable.value_u32;
1303c5486d4SThu Nguyen             minValue = pdr->min_readable.value_u32;
1313c5486d4SThu Nguyen             hysteresis = pdr->hysteresis.value_u32;
1323c5486d4SThu Nguyen             break;
1333c5486d4SThu Nguyen         case PLDM_SENSOR_DATA_SIZE_SINT32:
1343c5486d4SThu Nguyen             maxValue = pdr->max_readable.value_s32;
1353c5486d4SThu Nguyen             minValue = pdr->min_readable.value_s32;
1363c5486d4SThu Nguyen             hysteresis = pdr->hysteresis.value_s32;
1373c5486d4SThu Nguyen             break;
1383c5486d4SThu Nguyen     }
1393c5486d4SThu Nguyen 
1403c5486d4SThu Nguyen     bool hasCriticalThresholds = false;
1413c5486d4SThu Nguyen     bool hasWarningThresholds = false;
1423c5486d4SThu Nguyen     double criticalHigh = std::numeric_limits<double>::quiet_NaN();
1433c5486d4SThu Nguyen     double criticalLow = std::numeric_limits<double>::quiet_NaN();
1443c5486d4SThu Nguyen     double warningHigh = std::numeric_limits<double>::quiet_NaN();
1453c5486d4SThu Nguyen     double warningLow = std::numeric_limits<double>::quiet_NaN();
1463c5486d4SThu Nguyen 
1473c5486d4SThu Nguyen     if (pdr->supported_thresholds.bits.bit0)
1483c5486d4SThu Nguyen     {
1493c5486d4SThu Nguyen         hasWarningThresholds = true;
1503c5486d4SThu Nguyen         switch (pdr->range_field_format)
1513c5486d4SThu Nguyen         {
1523c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT8:
1533c5486d4SThu Nguyen                 warningHigh = pdr->warning_high.value_u8;
1543c5486d4SThu Nguyen                 break;
1553c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT8:
1563c5486d4SThu Nguyen                 warningHigh = pdr->warning_high.value_s8;
1573c5486d4SThu Nguyen                 break;
1583c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT16:
1593c5486d4SThu Nguyen                 warningHigh = pdr->warning_high.value_u16;
1603c5486d4SThu Nguyen                 break;
1613c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT16:
1623c5486d4SThu Nguyen                 warningHigh = pdr->warning_high.value_s16;
1633c5486d4SThu Nguyen                 break;
1643c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT32:
1653c5486d4SThu Nguyen                 warningHigh = pdr->warning_high.value_u32;
1663c5486d4SThu Nguyen                 break;
1673c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT32:
1683c5486d4SThu Nguyen                 warningHigh = pdr->warning_high.value_s32;
1693c5486d4SThu Nguyen                 break;
1703c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_REAL32:
1713c5486d4SThu Nguyen                 warningHigh = pdr->warning_high.value_f32;
1723c5486d4SThu Nguyen                 break;
1733c5486d4SThu Nguyen         }
1743c5486d4SThu Nguyen     }
1753c5486d4SThu Nguyen 
1763c5486d4SThu Nguyen     if (pdr->supported_thresholds.bits.bit3)
1773c5486d4SThu Nguyen     {
1783c5486d4SThu Nguyen         hasWarningThresholds = true;
1793c5486d4SThu Nguyen         switch (pdr->range_field_format)
1803c5486d4SThu Nguyen         {
1813c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT8:
1823c5486d4SThu Nguyen                 warningLow = pdr->warning_low.value_u8;
1833c5486d4SThu Nguyen                 break;
1843c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT8:
1853c5486d4SThu Nguyen                 warningLow = pdr->warning_low.value_s8;
1863c5486d4SThu Nguyen                 break;
1873c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT16:
1883c5486d4SThu Nguyen                 warningLow = pdr->warning_low.value_u16;
1893c5486d4SThu Nguyen                 break;
1903c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT16:
1913c5486d4SThu Nguyen                 warningLow = pdr->warning_low.value_s16;
1923c5486d4SThu Nguyen                 break;
1933c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT32:
1943c5486d4SThu Nguyen                 warningLow = pdr->warning_low.value_u32;
1953c5486d4SThu Nguyen                 break;
1963c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT32:
1973c5486d4SThu Nguyen                 warningLow = pdr->warning_low.value_s32;
1983c5486d4SThu Nguyen                 break;
1993c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_REAL32:
2003c5486d4SThu Nguyen                 warningLow = pdr->warning_low.value_f32;
2013c5486d4SThu Nguyen                 break;
2023c5486d4SThu Nguyen         }
2033c5486d4SThu Nguyen     }
2043c5486d4SThu Nguyen 
2053c5486d4SThu Nguyen     if (pdr->supported_thresholds.bits.bit1)
2063c5486d4SThu Nguyen     {
2073c5486d4SThu Nguyen         hasCriticalThresholds = true;
2083c5486d4SThu Nguyen         switch (pdr->range_field_format)
2093c5486d4SThu Nguyen         {
2103c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT8:
2113c5486d4SThu Nguyen                 criticalHigh = pdr->critical_high.value_u8;
2123c5486d4SThu Nguyen                 break;
2133c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT8:
2143c5486d4SThu Nguyen                 criticalHigh = pdr->critical_high.value_s8;
2153c5486d4SThu Nguyen                 break;
2163c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT16:
2173c5486d4SThu Nguyen                 criticalHigh = pdr->critical_high.value_u16;
2183c5486d4SThu Nguyen                 break;
2193c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT16:
2203c5486d4SThu Nguyen                 criticalHigh = pdr->critical_high.value_s16;
2213c5486d4SThu Nguyen                 break;
2223c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT32:
2233c5486d4SThu Nguyen                 criticalHigh = pdr->critical_high.value_u32;
2243c5486d4SThu Nguyen                 break;
2253c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT32:
2263c5486d4SThu Nguyen                 criticalHigh = pdr->critical_high.value_s32;
2273c5486d4SThu Nguyen                 break;
2283c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_REAL32:
2293c5486d4SThu Nguyen                 criticalHigh = pdr->critical_high.value_f32;
2303c5486d4SThu Nguyen                 break;
2313c5486d4SThu Nguyen         }
2323c5486d4SThu Nguyen     }
2333c5486d4SThu Nguyen 
2343c5486d4SThu Nguyen     if (pdr->supported_thresholds.bits.bit4)
2353c5486d4SThu Nguyen     {
2363c5486d4SThu Nguyen         hasCriticalThresholds = true;
2373c5486d4SThu Nguyen         switch (pdr->range_field_format)
2383c5486d4SThu Nguyen         {
2393c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT8:
2403c5486d4SThu Nguyen                 criticalLow = pdr->critical_low.value_u8;
2413c5486d4SThu Nguyen                 break;
2423c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT8:
2433c5486d4SThu Nguyen                 criticalLow = pdr->critical_low.value_s8;
2443c5486d4SThu Nguyen                 break;
2453c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT16:
2463c5486d4SThu Nguyen                 criticalLow = pdr->critical_low.value_u16;
2473c5486d4SThu Nguyen                 break;
2483c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT16:
2493c5486d4SThu Nguyen                 criticalLow = pdr->critical_low.value_s16;
2503c5486d4SThu Nguyen                 break;
2513c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_UINT32:
2523c5486d4SThu Nguyen                 criticalLow = pdr->critical_low.value_u32;
2533c5486d4SThu Nguyen                 break;
2543c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_SINT32:
2553c5486d4SThu Nguyen                 criticalLow = pdr->critical_low.value_s32;
2563c5486d4SThu Nguyen                 break;
2573c5486d4SThu Nguyen             case PLDM_RANGE_FIELD_FORMAT_REAL32:
2583c5486d4SThu Nguyen                 criticalLow = pdr->critical_low.value_f32;
2593c5486d4SThu Nguyen                 break;
2603c5486d4SThu Nguyen         }
2613c5486d4SThu Nguyen     }
2623c5486d4SThu Nguyen 
2633c5486d4SThu Nguyen     resolution = pdr->resolution;
2643c5486d4SThu Nguyen     offset = pdr->offset;
2653c5486d4SThu Nguyen     baseUnitModifier = pdr->unit_modifier;
266*eac61a4bSGilbert Chen     timeStamp = 0;
2673c5486d4SThu Nguyen 
2683c5486d4SThu Nguyen     /**
2693c5486d4SThu Nguyen      * DEFAULT_SENSOR_UPDATER_INTERVAL is in milliseconds
2703c5486d4SThu Nguyen      * updateTime is in microseconds
2713c5486d4SThu Nguyen      */
2723c5486d4SThu Nguyen     updateTime = static_cast<uint64_t>(DEFAULT_SENSOR_UPDATER_INTERVAL * 1000);
2733c5486d4SThu Nguyen     if (!std::isnan(pdr->update_interval))
2743c5486d4SThu Nguyen     {
2753c5486d4SThu Nguyen         updateTime = pdr->update_interval * 1000000;
2763c5486d4SThu Nguyen     }
2773c5486d4SThu Nguyen 
2783c5486d4SThu Nguyen     try
2793c5486d4SThu Nguyen     {
2803c5486d4SThu Nguyen         valueIntf = std::make_unique<ValueIntf>(bus, path.c_str());
2813c5486d4SThu Nguyen     }
2823c5486d4SThu Nguyen     catch (const sdbusplus::exception_t& e)
2833c5486d4SThu Nguyen     {
2843c5486d4SThu Nguyen         lg2::error(
2853c5486d4SThu Nguyen             "Failed to create Value interface for numeric sensor {PATH} error - {ERROR}",
2863c5486d4SThu Nguyen             "PATH", path, "ERROR", e);
2873c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
2883c5486d4SThu Nguyen     }
2893c5486d4SThu Nguyen     valueIntf->maxValue(unitModifier(conversionFormula(maxValue)));
2903c5486d4SThu Nguyen     valueIntf->minValue(unitModifier(conversionFormula(minValue)));
2913c5486d4SThu Nguyen     hysteresis = unitModifier(conversionFormula(hysteresis));
2923c5486d4SThu Nguyen     valueIntf->unit(sensorUnit);
2933c5486d4SThu Nguyen 
2943c5486d4SThu Nguyen     try
2953c5486d4SThu Nguyen     {
29616c2a0a0SPatrick Williams         availabilityIntf =
29716c2a0a0SPatrick Williams             std::make_unique<AvailabilityIntf>(bus, path.c_str());
2983c5486d4SThu Nguyen     }
2993c5486d4SThu Nguyen     catch (const sdbusplus::exception_t& e)
3003c5486d4SThu Nguyen     {
3013c5486d4SThu Nguyen         lg2::error(
3023c5486d4SThu Nguyen             "Failed to create Availability interface for numeric sensor {PATH} error - {ERROR}",
3033c5486d4SThu Nguyen             "PATH", path, "ERROR", e);
3043c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
3053c5486d4SThu Nguyen     }
3063c5486d4SThu Nguyen     availabilityIntf->available(true);
3073c5486d4SThu Nguyen 
3083c5486d4SThu Nguyen     try
3093c5486d4SThu Nguyen     {
3103c5486d4SThu Nguyen         operationalStatusIntf =
3113c5486d4SThu Nguyen             std::make_unique<OperationalStatusIntf>(bus, path.c_str());
3123c5486d4SThu Nguyen     }
3133c5486d4SThu Nguyen     catch (const sdbusplus::exception_t& e)
3143c5486d4SThu Nguyen     {
3153c5486d4SThu Nguyen         lg2::error(
3163c5486d4SThu Nguyen             "Failed to create Operation status interface for numeric sensor {PATH} error - {ERROR}",
3173c5486d4SThu Nguyen             "PATH", path, "ERROR", e);
3183c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
3193c5486d4SThu Nguyen     }
3203c5486d4SThu Nguyen     operationalStatusIntf->functional(!sensorDisabled);
3213c5486d4SThu Nguyen 
3223c5486d4SThu Nguyen     if (hasWarningThresholds)
3233c5486d4SThu Nguyen     {
3243c5486d4SThu Nguyen         try
3253c5486d4SThu Nguyen         {
3263c5486d4SThu Nguyen             thresholdWarningIntf =
3273c5486d4SThu Nguyen                 std::make_unique<ThresholdWarningIntf>(bus, path.c_str());
3283c5486d4SThu Nguyen         }
3293c5486d4SThu Nguyen         catch (const sdbusplus::exception_t& e)
3303c5486d4SThu Nguyen         {
3313c5486d4SThu Nguyen             lg2::error(
3323c5486d4SThu Nguyen                 "Failed to create Threshold warning interface for numeric sensor {PATH} error - {ERROR}",
3333c5486d4SThu Nguyen                 "PATH", path, "ERROR", e);
3343c5486d4SThu Nguyen             throw sdbusplus::xyz::openbmc_project::Common::Error::
3353c5486d4SThu Nguyen                 InvalidArgument();
3363c5486d4SThu Nguyen         }
3373c5486d4SThu Nguyen         thresholdWarningIntf->warningHigh(unitModifier(warningHigh));
3383c5486d4SThu Nguyen         thresholdWarningIntf->warningLow(unitModifier(warningLow));
3393c5486d4SThu Nguyen     }
3403c5486d4SThu Nguyen 
3413c5486d4SThu Nguyen     if (hasCriticalThresholds)
3423c5486d4SThu Nguyen     {
3433c5486d4SThu Nguyen         try
3443c5486d4SThu Nguyen         {
3453c5486d4SThu Nguyen             thresholdCriticalIntf =
3463c5486d4SThu Nguyen                 std::make_unique<ThresholdCriticalIntf>(bus, path.c_str());
3473c5486d4SThu Nguyen         }
3483c5486d4SThu Nguyen         catch (const sdbusplus::exception_t& e)
3493c5486d4SThu Nguyen         {
3503c5486d4SThu Nguyen             lg2::error(
3513c5486d4SThu Nguyen                 "Failed to create Threshold critical interface for numeric sensor {PATH} error - {ERROR}",
3523c5486d4SThu Nguyen                 "PATH", path, "ERROR", e);
3533c5486d4SThu Nguyen             throw sdbusplus::xyz::openbmc_project::Common::Error::
3543c5486d4SThu Nguyen                 InvalidArgument();
3553c5486d4SThu Nguyen         }
3563c5486d4SThu Nguyen         thresholdCriticalIntf->criticalHigh(unitModifier(criticalHigh));
3573c5486d4SThu Nguyen         thresholdCriticalIntf->criticalLow(unitModifier(criticalLow));
3583c5486d4SThu Nguyen     }
3593c5486d4SThu Nguyen }
3603c5486d4SThu Nguyen 
NumericSensor(const pldm_tid_t tid,const bool sensorDisabled,std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr,std::string & sensorName,std::string & associationPath)3613c5486d4SThu Nguyen NumericSensor::NumericSensor(
3623c5486d4SThu Nguyen     const pldm_tid_t tid, const bool sensorDisabled,
3633c5486d4SThu Nguyen     std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr,
3643c5486d4SThu Nguyen     std::string& sensorName, std::string& associationPath) :
365*eac61a4bSGilbert Chen     tid(tid), sensorName(sensorName)
3663c5486d4SThu Nguyen {
3673c5486d4SThu Nguyen     if (!pdr)
3683c5486d4SThu Nguyen     {
3693c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
3703c5486d4SThu Nguyen     }
3713c5486d4SThu Nguyen 
3723c5486d4SThu Nguyen     sensorId = pdr->sensor_id;
3733c5486d4SThu Nguyen     std::string path;
3743c5486d4SThu Nguyen     SensorUnit sensorUnit = SensorUnit::DegreesC;
3753c5486d4SThu Nguyen 
3763c5486d4SThu Nguyen     switch (pdr->base_unit)
3773c5486d4SThu Nguyen     {
3783c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_DEGRESS_C:
3793c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/temperature/";
3803c5486d4SThu Nguyen             sensorUnit = SensorUnit::DegreesC;
3813c5486d4SThu Nguyen             break;
3823c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_VOLTS:
3833c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/voltage/";
3843c5486d4SThu Nguyen             sensorUnit = SensorUnit::Volts;
3853c5486d4SThu Nguyen             break;
3863c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_AMPS:
3873c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/current/";
3883c5486d4SThu Nguyen             sensorUnit = SensorUnit::Amperes;
3893c5486d4SThu Nguyen             break;
3903c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_RPM:
3913c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/fan_pwm/";
3923c5486d4SThu Nguyen             sensorUnit = SensorUnit::RPMS;
3933c5486d4SThu Nguyen             break;
3943c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_WATTS:
3953c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/power/";
3963c5486d4SThu Nguyen             sensorUnit = SensorUnit::Watts;
3973c5486d4SThu Nguyen             break;
3983c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_JOULES:
3993c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/energy/";
4003c5486d4SThu Nguyen             sensorUnit = SensorUnit::Joules;
4013c5486d4SThu Nguyen             break;
4023c5486d4SThu Nguyen         case PLDM_SENSOR_UNIT_PERCENTAGE:
4033c5486d4SThu Nguyen             sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/";
4043c5486d4SThu Nguyen             sensorUnit = SensorUnit::Percent;
4053c5486d4SThu Nguyen             break;
4063c5486d4SThu Nguyen         default:
4073c5486d4SThu Nguyen             lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME",
4083c5486d4SThu Nguyen                        sensorName, "UNIT", pdr->base_unit);
4093c5486d4SThu Nguyen             throw sdbusplus::xyz::openbmc_project::Common::Error::
4103c5486d4SThu Nguyen                 InvalidArgument();
4113c5486d4SThu Nguyen             break;
4123c5486d4SThu Nguyen     }
4133c5486d4SThu Nguyen 
4143c5486d4SThu Nguyen     path = sensorNameSpace + sensorName;
4153c5486d4SThu Nguyen     try
4163c5486d4SThu Nguyen     {
4173c5486d4SThu Nguyen         auto service = pldm::utils::DBusHandler().getService(
4183c5486d4SThu Nguyen             path.c_str(), "xyz.openbmc_project.Sensor.Value");
4193c5486d4SThu Nguyen         if (!service.empty())
4203c5486d4SThu Nguyen         {
4213c5486d4SThu Nguyen             throw sdbusplus::xyz::openbmc_project::Common::Error::
4223c5486d4SThu Nguyen                 TooManyResources();
4233c5486d4SThu Nguyen         }
4243c5486d4SThu Nguyen     }
4253c5486d4SThu Nguyen     catch (const std::exception&)
4263c5486d4SThu Nguyen     {
4273c5486d4SThu Nguyen         /* The sensor object path is not created */
4283c5486d4SThu Nguyen     }
4293c5486d4SThu Nguyen 
4303c5486d4SThu Nguyen     auto& bus = pldm::utils::DBusHandler::getBus();
4313c5486d4SThu Nguyen     try
4323c5486d4SThu Nguyen     {
4333c5486d4SThu Nguyen         associationDefinitionsIntf =
4343c5486d4SThu Nguyen             std::make_unique<AssociationDefinitionsInft>(bus, path.c_str());
4353c5486d4SThu Nguyen     }
4363c5486d4SThu Nguyen     catch (const sdbusplus::exception_t& e)
4373c5486d4SThu Nguyen     {
4383c5486d4SThu Nguyen         lg2::error(
4393c5486d4SThu Nguyen             "Failed to create Association interface for compact numeric sensor {PATH} error - {ERROR}",
4403c5486d4SThu Nguyen             "PATH", path, "ERROR", e);
4413c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
4423c5486d4SThu Nguyen     }
4433c5486d4SThu Nguyen     associationDefinitionsIntf->associations(
4443c5486d4SThu Nguyen         {{"chassis", "all_sensors", associationPath.c_str()}});
4453c5486d4SThu Nguyen 
4463c5486d4SThu Nguyen     double maxValue = std::numeric_limits<double>::quiet_NaN();
4473c5486d4SThu Nguyen     double minValue = std::numeric_limits<double>::quiet_NaN();
4483c5486d4SThu Nguyen     bool hasWarningThresholds = false;
4493c5486d4SThu Nguyen     bool hasCriticalThresholds = false;
4503c5486d4SThu Nguyen     double criticalHigh = std::numeric_limits<double>::quiet_NaN();
4513c5486d4SThu Nguyen     double criticalLow = std::numeric_limits<double>::quiet_NaN();
4523c5486d4SThu Nguyen     double warningHigh = std::numeric_limits<double>::quiet_NaN();
4533c5486d4SThu Nguyen     double warningLow = std::numeric_limits<double>::quiet_NaN();
4543c5486d4SThu Nguyen 
4553c5486d4SThu Nguyen     if (pdr->range_field_support.bits.bit0)
4563c5486d4SThu Nguyen     {
4573c5486d4SThu Nguyen         hasWarningThresholds = true;
4583c5486d4SThu Nguyen         warningHigh = pdr->warning_high;
4593c5486d4SThu Nguyen     }
4603c5486d4SThu Nguyen     if (pdr->range_field_support.bits.bit1)
4613c5486d4SThu Nguyen     {
4623c5486d4SThu Nguyen         hasWarningThresholds = true;
4633c5486d4SThu Nguyen         warningLow = pdr->warning_low;
4643c5486d4SThu Nguyen     }
4653c5486d4SThu Nguyen 
4663c5486d4SThu Nguyen     if (pdr->range_field_support.bits.bit2)
4673c5486d4SThu Nguyen     {
4683c5486d4SThu Nguyen         hasCriticalThresholds = true;
4693c5486d4SThu Nguyen         criticalHigh = pdr->critical_high;
4703c5486d4SThu Nguyen     }
4713c5486d4SThu Nguyen 
4723c5486d4SThu Nguyen     if (pdr->range_field_support.bits.bit3)
4733c5486d4SThu Nguyen     {
4743c5486d4SThu Nguyen         hasCriticalThresholds = true;
4753c5486d4SThu Nguyen         criticalLow = pdr->critical_low;
4763c5486d4SThu Nguyen     }
4773c5486d4SThu Nguyen 
4783c5486d4SThu Nguyen     resolution = std::numeric_limits<double>::quiet_NaN();
4793c5486d4SThu Nguyen     offset = std::numeric_limits<double>::quiet_NaN();
4803c5486d4SThu Nguyen     baseUnitModifier = pdr->unit_modifier;
481*eac61a4bSGilbert Chen     timeStamp = 0;
4823c5486d4SThu Nguyen 
4833c5486d4SThu Nguyen     /**
4843c5486d4SThu Nguyen      * DEFAULT_SENSOR_UPDATER_INTERVAL is in milliseconds
4853c5486d4SThu Nguyen      * updateTime is in microseconds
4863c5486d4SThu Nguyen      */
4873c5486d4SThu Nguyen     updateTime = static_cast<uint64_t>(DEFAULT_SENSOR_UPDATER_INTERVAL * 1000);
4883c5486d4SThu Nguyen     try
4893c5486d4SThu Nguyen     {
4903c5486d4SThu Nguyen         valueIntf = std::make_unique<ValueIntf>(bus, path.c_str());
4913c5486d4SThu Nguyen     }
4923c5486d4SThu Nguyen     catch (const sdbusplus::exception_t& e)
4933c5486d4SThu Nguyen     {
4943c5486d4SThu Nguyen         lg2::error(
4953c5486d4SThu Nguyen             "Failed to create Value interface for compact numeric sensor {PATH} error - {ERROR}",
4963c5486d4SThu Nguyen             "PATH", path, "ERROR", e);
4973c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
4983c5486d4SThu Nguyen     }
4993c5486d4SThu Nguyen     valueIntf->maxValue(unitModifier(conversionFormula(maxValue)));
5003c5486d4SThu Nguyen     valueIntf->minValue(unitModifier(conversionFormula(minValue)));
5013c5486d4SThu Nguyen     hysteresis = unitModifier(conversionFormula(hysteresis));
5023c5486d4SThu Nguyen     valueIntf->unit(sensorUnit);
5033c5486d4SThu Nguyen 
5043c5486d4SThu Nguyen     try
5053c5486d4SThu Nguyen     {
50616c2a0a0SPatrick Williams         availabilityIntf =
50716c2a0a0SPatrick Williams             std::make_unique<AvailabilityIntf>(bus, path.c_str());
5083c5486d4SThu Nguyen     }
5093c5486d4SThu Nguyen     catch (const sdbusplus::exception_t& e)
5103c5486d4SThu Nguyen     {
5113c5486d4SThu Nguyen         lg2::error(
5123c5486d4SThu Nguyen             "Failed to create Availability interface for compact numeric sensor {PATH} error - {ERROR}",
5133c5486d4SThu Nguyen             "PATH", path, "ERROR", e);
5143c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
5153c5486d4SThu Nguyen     }
5163c5486d4SThu Nguyen     availabilityIntf->available(true);
5173c5486d4SThu Nguyen 
5183c5486d4SThu Nguyen     try
5193c5486d4SThu Nguyen     {
5203c5486d4SThu Nguyen         operationalStatusIntf =
5213c5486d4SThu Nguyen             std::make_unique<OperationalStatusIntf>(bus, path.c_str());
5223c5486d4SThu Nguyen     }
5233c5486d4SThu Nguyen     catch (const sdbusplus::exception_t& e)
5243c5486d4SThu Nguyen     {
5253c5486d4SThu Nguyen         lg2::error(
5263c5486d4SThu Nguyen             "Failed to create Operational status interface for compact numeric sensor {PATH} error - {ERROR}",
5273c5486d4SThu Nguyen             "PATH", path, "ERROR", e);
5283c5486d4SThu Nguyen         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
5293c5486d4SThu Nguyen     }
5303c5486d4SThu Nguyen     operationalStatusIntf->functional(!sensorDisabled);
5313c5486d4SThu Nguyen 
5323c5486d4SThu Nguyen     if (hasWarningThresholds)
5333c5486d4SThu Nguyen     {
5343c5486d4SThu Nguyen         try
5353c5486d4SThu Nguyen         {
5363c5486d4SThu Nguyen             thresholdWarningIntf =
5373c5486d4SThu Nguyen                 std::make_unique<ThresholdWarningIntf>(bus, path.c_str());
5383c5486d4SThu Nguyen         }
5393c5486d4SThu Nguyen         catch (const sdbusplus::exception_t& e)
5403c5486d4SThu Nguyen         {
5413c5486d4SThu Nguyen             lg2::error(
5423c5486d4SThu Nguyen                 "Failed to create Warning threshold interface for compact numeric sensor {PATH} error - {ERROR}",
5433c5486d4SThu Nguyen                 "PATH", path, "ERROR", e);
5443c5486d4SThu Nguyen             throw sdbusplus::xyz::openbmc_project::Common::Error::
5453c5486d4SThu Nguyen                 InvalidArgument();
5463c5486d4SThu Nguyen         }
5473c5486d4SThu Nguyen         thresholdWarningIntf->warningHigh(unitModifier(warningHigh));
5483c5486d4SThu Nguyen         thresholdWarningIntf->warningLow(unitModifier(warningLow));
5493c5486d4SThu Nguyen     }
5503c5486d4SThu Nguyen 
5513c5486d4SThu Nguyen     if (hasCriticalThresholds)
5523c5486d4SThu Nguyen     {
5533c5486d4SThu Nguyen         try
5543c5486d4SThu Nguyen         {
5553c5486d4SThu Nguyen             thresholdCriticalIntf =
5563c5486d4SThu Nguyen                 std::make_unique<ThresholdCriticalIntf>(bus, path.c_str());
5573c5486d4SThu Nguyen         }
5583c5486d4SThu Nguyen         catch (const sdbusplus::exception_t& e)
5593c5486d4SThu Nguyen         {
5603c5486d4SThu Nguyen             lg2::error(
5613c5486d4SThu Nguyen                 "Failed to create Critical threshold interface for compact numeric sensor {PATH} error - {ERROR}",
5623c5486d4SThu Nguyen                 "PATH", path, "ERROR", e);
5633c5486d4SThu Nguyen             throw sdbusplus::xyz::openbmc_project::Common::Error::
5643c5486d4SThu Nguyen                 InvalidArgument();
5653c5486d4SThu Nguyen         }
5663c5486d4SThu Nguyen         thresholdCriticalIntf->criticalHigh(unitModifier(criticalHigh));
5673c5486d4SThu Nguyen         thresholdCriticalIntf->criticalLow(unitModifier(criticalLow));
5683c5486d4SThu Nguyen     }
5693c5486d4SThu Nguyen }
5703c5486d4SThu Nguyen 
conversionFormula(double value)5713c5486d4SThu Nguyen double NumericSensor::conversionFormula(double value)
5723c5486d4SThu Nguyen {
5733c5486d4SThu Nguyen     double convertedValue = value;
5743c5486d4SThu Nguyen     convertedValue *= std::isnan(resolution) ? 1 : resolution;
5753c5486d4SThu Nguyen     convertedValue += std::isnan(offset) ? 0 : offset;
5763c5486d4SThu Nguyen     return convertedValue;
5773c5486d4SThu Nguyen }
5783c5486d4SThu Nguyen 
unitModifier(double value)5793c5486d4SThu Nguyen double NumericSensor::unitModifier(double value)
5803c5486d4SThu Nguyen {
5813c5486d4SThu Nguyen     return std::isnan(value) ? value : value * std::pow(10, baseUnitModifier);
5823c5486d4SThu Nguyen }
583*eac61a4bSGilbert Chen 
updateReading(bool available,bool functional,double value)584*eac61a4bSGilbert Chen void NumericSensor::updateReading(bool available, bool functional, double value)
585*eac61a4bSGilbert Chen {
586*eac61a4bSGilbert Chen     if (!availabilityIntf || !operationalStatusIntf || !valueIntf)
587*eac61a4bSGilbert Chen     {
588*eac61a4bSGilbert Chen         lg2::error(
589*eac61a4bSGilbert Chen             "Failed to update sensor {NAME} D-Bus interface don't exist.",
590*eac61a4bSGilbert Chen             "NAME", sensorName);
591*eac61a4bSGilbert Chen         return;
592*eac61a4bSGilbert Chen     }
593*eac61a4bSGilbert Chen     availabilityIntf->available(available);
594*eac61a4bSGilbert Chen     operationalStatusIntf->functional(functional);
595*eac61a4bSGilbert Chen     double curValue = valueIntf->value();
596*eac61a4bSGilbert Chen     double newValue = std::numeric_limits<double>::quiet_NaN();
597*eac61a4bSGilbert Chen     if (functional && available)
598*eac61a4bSGilbert Chen     {
599*eac61a4bSGilbert Chen         newValue = unitModifier(conversionFormula(value));
600*eac61a4bSGilbert Chen         if (newValue != curValue &&
601*eac61a4bSGilbert Chen             (!std::isnan(newValue) || !std::isnan(curValue)))
602*eac61a4bSGilbert Chen         {
603*eac61a4bSGilbert Chen             valueIntf->value(newValue);
604*eac61a4bSGilbert Chen             updateThresholds();
605*eac61a4bSGilbert Chen         }
606*eac61a4bSGilbert Chen     }
607*eac61a4bSGilbert Chen     else
608*eac61a4bSGilbert Chen     {
609*eac61a4bSGilbert Chen         if (newValue != curValue &&
610*eac61a4bSGilbert Chen             (!std::isnan(newValue) || !std::isnan(curValue)))
611*eac61a4bSGilbert Chen         {
612*eac61a4bSGilbert Chen             valueIntf->value(std::numeric_limits<double>::quiet_NaN());
613*eac61a4bSGilbert Chen         }
614*eac61a4bSGilbert Chen     }
615*eac61a4bSGilbert Chen }
616*eac61a4bSGilbert Chen 
handleErrGetSensorReading()617*eac61a4bSGilbert Chen void NumericSensor::handleErrGetSensorReading()
618*eac61a4bSGilbert Chen {
619*eac61a4bSGilbert Chen     if (!operationalStatusIntf || !valueIntf)
620*eac61a4bSGilbert Chen     {
621*eac61a4bSGilbert Chen         lg2::error(
622*eac61a4bSGilbert Chen             "Failed to update sensor {NAME} D-Bus interfaces don't exist.",
623*eac61a4bSGilbert Chen             "NAME", sensorName);
624*eac61a4bSGilbert Chen         return;
625*eac61a4bSGilbert Chen     }
626*eac61a4bSGilbert Chen     operationalStatusIntf->functional(false);
627*eac61a4bSGilbert Chen     valueIntf->value(std::numeric_limits<double>::quiet_NaN());
628*eac61a4bSGilbert Chen }
629*eac61a4bSGilbert Chen 
checkThreshold(bool alarm,bool direction,double value,double threshold,double hyst)630*eac61a4bSGilbert Chen bool NumericSensor::checkThreshold(bool alarm, bool direction, double value,
631*eac61a4bSGilbert Chen                                    double threshold, double hyst)
632*eac61a4bSGilbert Chen {
633*eac61a4bSGilbert Chen     if (direction)
634*eac61a4bSGilbert Chen     {
635*eac61a4bSGilbert Chen         if (value >= threshold)
636*eac61a4bSGilbert Chen         {
637*eac61a4bSGilbert Chen             return true;
638*eac61a4bSGilbert Chen         }
639*eac61a4bSGilbert Chen         if (value < (threshold - hyst))
640*eac61a4bSGilbert Chen         {
641*eac61a4bSGilbert Chen             return false;
642*eac61a4bSGilbert Chen         }
643*eac61a4bSGilbert Chen     }
644*eac61a4bSGilbert Chen     else
645*eac61a4bSGilbert Chen     {
646*eac61a4bSGilbert Chen         if (value <= threshold)
647*eac61a4bSGilbert Chen         {
648*eac61a4bSGilbert Chen             return true;
649*eac61a4bSGilbert Chen         }
650*eac61a4bSGilbert Chen         if (value > (threshold + hyst))
651*eac61a4bSGilbert Chen         {
652*eac61a4bSGilbert Chen             return false;
653*eac61a4bSGilbert Chen         }
654*eac61a4bSGilbert Chen     }
655*eac61a4bSGilbert Chen     return alarm;
656*eac61a4bSGilbert Chen }
657*eac61a4bSGilbert Chen 
updateThresholds()658*eac61a4bSGilbert Chen void NumericSensor::updateThresholds()
659*eac61a4bSGilbert Chen {
660*eac61a4bSGilbert Chen     if (!valueIntf)
661*eac61a4bSGilbert Chen     {
662*eac61a4bSGilbert Chen         lg2::error(
663*eac61a4bSGilbert Chen             "Failed to update thresholds sensor {NAME} D-Bus interfaces don't exist.",
664*eac61a4bSGilbert Chen             "NAME", sensorName);
665*eac61a4bSGilbert Chen         return;
666*eac61a4bSGilbert Chen     }
667*eac61a4bSGilbert Chen 
668*eac61a4bSGilbert Chen     auto value = valueIntf->value();
669*eac61a4bSGilbert Chen 
670*eac61a4bSGilbert Chen     if (thresholdWarningIntf &&
671*eac61a4bSGilbert Chen         !std::isnan(thresholdWarningIntf->warningHigh()))
672*eac61a4bSGilbert Chen     {
673*eac61a4bSGilbert Chen         auto threshold = thresholdWarningIntf->warningHigh();
674*eac61a4bSGilbert Chen         auto alarm = thresholdWarningIntf->warningAlarmHigh();
675*eac61a4bSGilbert Chen         auto newAlarm =
676*eac61a4bSGilbert Chen             checkThreshold(alarm, true, value, threshold, hysteresis);
677*eac61a4bSGilbert Chen         if (alarm != newAlarm)
678*eac61a4bSGilbert Chen         {
679*eac61a4bSGilbert Chen             thresholdWarningIntf->warningAlarmHigh(newAlarm);
680*eac61a4bSGilbert Chen             if (newAlarm)
681*eac61a4bSGilbert Chen             {
682*eac61a4bSGilbert Chen                 thresholdWarningIntf->warningHighAlarmAsserted(value);
683*eac61a4bSGilbert Chen             }
684*eac61a4bSGilbert Chen             else
685*eac61a4bSGilbert Chen             {
686*eac61a4bSGilbert Chen                 thresholdWarningIntf->warningHighAlarmDeasserted(value);
687*eac61a4bSGilbert Chen             }
688*eac61a4bSGilbert Chen         }
689*eac61a4bSGilbert Chen     }
690*eac61a4bSGilbert Chen 
691*eac61a4bSGilbert Chen     if (thresholdWarningIntf && !std::isnan(thresholdWarningIntf->warningLow()))
692*eac61a4bSGilbert Chen     {
693*eac61a4bSGilbert Chen         auto threshold = thresholdWarningIntf->warningLow();
694*eac61a4bSGilbert Chen         auto alarm = thresholdWarningIntf->warningAlarmLow();
695*eac61a4bSGilbert Chen         auto newAlarm =
696*eac61a4bSGilbert Chen             checkThreshold(alarm, false, value, threshold, hysteresis);
697*eac61a4bSGilbert Chen         if (alarm != newAlarm)
698*eac61a4bSGilbert Chen         {
699*eac61a4bSGilbert Chen             thresholdWarningIntf->warningAlarmLow(newAlarm);
700*eac61a4bSGilbert Chen             if (newAlarm)
701*eac61a4bSGilbert Chen             {
702*eac61a4bSGilbert Chen                 thresholdWarningIntf->warningLowAlarmAsserted(value);
703*eac61a4bSGilbert Chen             }
704*eac61a4bSGilbert Chen             else
705*eac61a4bSGilbert Chen             {
706*eac61a4bSGilbert Chen                 thresholdWarningIntf->warningLowAlarmDeasserted(value);
707*eac61a4bSGilbert Chen             }
708*eac61a4bSGilbert Chen         }
709*eac61a4bSGilbert Chen     }
710*eac61a4bSGilbert Chen 
711*eac61a4bSGilbert Chen     if (thresholdCriticalIntf &&
712*eac61a4bSGilbert Chen         !std::isnan(thresholdCriticalIntf->criticalHigh()))
713*eac61a4bSGilbert Chen     {
714*eac61a4bSGilbert Chen         auto threshold = thresholdCriticalIntf->criticalHigh();
715*eac61a4bSGilbert Chen         auto alarm = thresholdCriticalIntf->criticalAlarmHigh();
716*eac61a4bSGilbert Chen         auto newAlarm =
717*eac61a4bSGilbert Chen             checkThreshold(alarm, true, value, threshold, hysteresis);
718*eac61a4bSGilbert Chen         if (alarm != newAlarm)
719*eac61a4bSGilbert Chen         {
720*eac61a4bSGilbert Chen             thresholdCriticalIntf->criticalAlarmHigh(newAlarm);
721*eac61a4bSGilbert Chen             if (newAlarm)
722*eac61a4bSGilbert Chen             {
723*eac61a4bSGilbert Chen                 thresholdCriticalIntf->criticalHighAlarmAsserted(value);
724*eac61a4bSGilbert Chen             }
725*eac61a4bSGilbert Chen             else
726*eac61a4bSGilbert Chen             {
727*eac61a4bSGilbert Chen                 thresholdCriticalIntf->criticalHighAlarmDeasserted(value);
728*eac61a4bSGilbert Chen             }
729*eac61a4bSGilbert Chen         }
730*eac61a4bSGilbert Chen     }
731*eac61a4bSGilbert Chen 
732*eac61a4bSGilbert Chen     if (thresholdCriticalIntf &&
733*eac61a4bSGilbert Chen         !std::isnan(thresholdCriticalIntf->criticalLow()))
734*eac61a4bSGilbert Chen     {
735*eac61a4bSGilbert Chen         auto threshold = thresholdCriticalIntf->criticalLow();
736*eac61a4bSGilbert Chen         auto alarm = thresholdCriticalIntf->criticalAlarmLow();
737*eac61a4bSGilbert Chen         auto newAlarm =
738*eac61a4bSGilbert Chen             checkThreshold(alarm, false, value, threshold, hysteresis);
739*eac61a4bSGilbert Chen         if (alarm != newAlarm)
740*eac61a4bSGilbert Chen         {
741*eac61a4bSGilbert Chen             thresholdCriticalIntf->criticalAlarmLow(newAlarm);
742*eac61a4bSGilbert Chen             if (newAlarm)
743*eac61a4bSGilbert Chen             {
744*eac61a4bSGilbert Chen                 thresholdCriticalIntf->criticalLowAlarmAsserted(value);
745*eac61a4bSGilbert Chen             }
746*eac61a4bSGilbert Chen             else
747*eac61a4bSGilbert Chen             {
748*eac61a4bSGilbert Chen                 thresholdCriticalIntf->criticalLowAlarmDeasserted(value);
749*eac61a4bSGilbert Chen             }
750*eac61a4bSGilbert Chen         }
751*eac61a4bSGilbert Chen     }
752*eac61a4bSGilbert Chen }
7533c5486d4SThu Nguyen } // namespace platform_mc
7543c5486d4SThu Nguyen } // namespace pldm
755