| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 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 |  | 
| Chau Ly | d197f09 | 2023-11-06 07:29:06 +0000 | [diff] [blame] | 18 | inline bool NumericSensor::createInventoryPath( | 
|  | 19 | const std::string& associationPath, const std::string& sensorName, | 
|  | 20 | const uint16_t entityType, const uint16_t entityInstanceNum, | 
|  | 21 | const uint16_t containerId) | 
|  | 22 | { | 
|  | 23 | auto& bus = pldm::utils::DBusHandler::getBus(); | 
|  | 24 | std::string invPath = associationPath + "/" + sensorName; | 
|  | 25 | try | 
|  | 26 | { | 
|  | 27 | entityIntf = std::make_unique<EntityIntf>(bus, invPath.c_str()); | 
|  | 28 | } | 
|  | 29 | catch (const sdbusplus::exception_t& e) | 
|  | 30 | { | 
|  | 31 | lg2::error( | 
|  | 32 | "Failed to create Entity interface for compact numeric sensor {PATH} error - {ERROR}", | 
|  | 33 | "PATH", invPath, "ERROR", e); | 
|  | 34 | return false; | 
|  | 35 | } | 
|  | 36 | entityIntf->entityType(entityType); | 
|  | 37 | entityIntf->entityInstanceNumber(entityInstanceNum); | 
|  | 38 | entityIntf->containerID(containerId); | 
|  | 39 |  | 
|  | 40 | return true; | 
|  | 41 | } | 
|  | 42 |  | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 43 | NumericSensor::NumericSensor( | 
|  | 44 | const pldm_tid_t tid, const bool sensorDisabled, | 
|  | 45 | std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr, std::string& sensorName, | 
|  | 46 | std::string& associationPath) : tid(tid), sensorName(sensorName) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 47 | { | 
|  | 48 | if (!pdr) | 
|  | 49 | { | 
|  | 50 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 51 | } | 
|  | 52 |  | 
|  | 53 | sensorId = pdr->sensor_id; | 
|  | 54 | std::string path; | 
|  | 55 | SensorUnit sensorUnit = SensorUnit::DegreesC; | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 56 | MetricUnit metricUnit = MetricUnit::Count; | 
|  | 57 | useMetricInterface = false; | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 58 |  | 
|  | 59 | switch (pdr->base_unit) | 
|  | 60 | { | 
|  | 61 | case PLDM_SENSOR_UNIT_DEGRESS_C: | 
|  | 62 | sensorNameSpace = "/xyz/openbmc_project/sensors/temperature/"; | 
|  | 63 | sensorUnit = SensorUnit::DegreesC; | 
|  | 64 | break; | 
|  | 65 | case PLDM_SENSOR_UNIT_VOLTS: | 
|  | 66 | sensorNameSpace = "/xyz/openbmc_project/sensors/voltage/"; | 
|  | 67 | sensorUnit = SensorUnit::Volts; | 
|  | 68 | break; | 
|  | 69 | case PLDM_SENSOR_UNIT_AMPS: | 
|  | 70 | sensorNameSpace = "/xyz/openbmc_project/sensors/current/"; | 
|  | 71 | sensorUnit = SensorUnit::Amperes; | 
|  | 72 | break; | 
|  | 73 | case PLDM_SENSOR_UNIT_RPM: | 
|  | 74 | sensorNameSpace = "/xyz/openbmc_project/sensors/fan_pwm/"; | 
|  | 75 | sensorUnit = SensorUnit::RPMS; | 
|  | 76 | break; | 
|  | 77 | case PLDM_SENSOR_UNIT_WATTS: | 
|  | 78 | sensorNameSpace = "/xyz/openbmc_project/sensors/power/"; | 
|  | 79 | sensorUnit = SensorUnit::Watts; | 
|  | 80 | break; | 
|  | 81 | case PLDM_SENSOR_UNIT_JOULES: | 
|  | 82 | sensorNameSpace = "/xyz/openbmc_project/sensors/energy/"; | 
|  | 83 | sensorUnit = SensorUnit::Joules; | 
|  | 84 | break; | 
|  | 85 | case PLDM_SENSOR_UNIT_PERCENTAGE: | 
|  | 86 | sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/"; | 
|  | 87 | sensorUnit = SensorUnit::Percent; | 
|  | 88 | break; | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 89 | case PLDM_SENSOR_UNIT_COUNTS: | 
|  | 90 | case PLDM_SENSOR_UNIT_CORRECTED_ERRORS: | 
|  | 91 | case PLDM_SENSOR_UNIT_UNCORRECTABLE_ERRORS: | 
|  | 92 | sensorNameSpace = "/xyz/openbmc_project/metric/count/"; | 
|  | 93 | useMetricInterface = true; | 
|  | 94 | break; | 
|  | 95 | case PLDM_SENSOR_UNIT_OEMUNIT: | 
|  | 96 | sensorNameSpace = "/xyz/openbmc_project/metric/oem/"; | 
|  | 97 | useMetricInterface = true; | 
|  | 98 | break; | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 99 | default: | 
|  | 100 | lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME", | 
|  | 101 | sensorName, "UNIT", pdr->base_unit); | 
|  | 102 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 103 | InvalidArgument(); | 
|  | 104 | break; | 
|  | 105 | } | 
|  | 106 |  | 
|  | 107 | path = sensorNameSpace + sensorName; | 
|  | 108 | try | 
|  | 109 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 110 | std::string tmp{}; | 
|  | 111 | std::string interface = SENSOR_VALUE_INTF; | 
|  | 112 | if (useMetricInterface) | 
|  | 113 | { | 
|  | 114 | interface = METRIC_VALUE_INTF; | 
|  | 115 | } | 
|  | 116 | tmp = pldm::utils::DBusHandler().getService(path.c_str(), | 
|  | 117 | interface.c_str()); | 
|  | 118 |  | 
|  | 119 | if (!tmp.empty()) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 120 | { | 
|  | 121 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 122 | TooManyResources(); | 
|  | 123 | } | 
|  | 124 | } | 
|  | 125 | catch (const std::exception&) | 
|  | 126 | { | 
|  | 127 | /* The sensor object path is not created */ | 
|  | 128 | } | 
|  | 129 |  | 
|  | 130 | auto& bus = pldm::utils::DBusHandler::getBus(); | 
|  | 131 | try | 
|  | 132 | { | 
|  | 133 | associationDefinitionsIntf = | 
|  | 134 | std::make_unique<AssociationDefinitionsInft>(bus, path.c_str()); | 
|  | 135 | } | 
|  | 136 | catch (const sdbusplus::exception_t& e) | 
|  | 137 | { | 
|  | 138 | lg2::error( | 
|  | 139 | "Failed to create association interface for numeric sensor {PATH} error - {ERROR}", | 
|  | 140 | "PATH", path, "ERROR", e); | 
|  | 141 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 | associationDefinitionsIntf->associations( | 
|  | 145 | {{"chassis", "all_sensors", associationPath}}); | 
|  | 146 |  | 
|  | 147 | double maxValue = std::numeric_limits<double>::quiet_NaN(); | 
|  | 148 | double minValue = std::numeric_limits<double>::quiet_NaN(); | 
|  | 149 |  | 
|  | 150 | switch (pdr->sensor_data_size) | 
|  | 151 | { | 
|  | 152 | case PLDM_SENSOR_DATA_SIZE_UINT8: | 
|  | 153 | maxValue = pdr->max_readable.value_u8; | 
|  | 154 | minValue = pdr->min_readable.value_u8; | 
|  | 155 | hysteresis = pdr->hysteresis.value_u8; | 
|  | 156 | break; | 
|  | 157 | case PLDM_SENSOR_DATA_SIZE_SINT8: | 
|  | 158 | maxValue = pdr->max_readable.value_s8; | 
|  | 159 | minValue = pdr->min_readable.value_s8; | 
|  | 160 | hysteresis = pdr->hysteresis.value_s8; | 
|  | 161 | break; | 
|  | 162 | case PLDM_SENSOR_DATA_SIZE_UINT16: | 
|  | 163 | maxValue = pdr->max_readable.value_u16; | 
|  | 164 | minValue = pdr->min_readable.value_u16; | 
|  | 165 | hysteresis = pdr->hysteresis.value_u16; | 
|  | 166 | break; | 
|  | 167 | case PLDM_SENSOR_DATA_SIZE_SINT16: | 
|  | 168 | maxValue = pdr->max_readable.value_s16; | 
|  | 169 | minValue = pdr->min_readable.value_s16; | 
|  | 170 | hysteresis = pdr->hysteresis.value_s16; | 
|  | 171 | break; | 
|  | 172 | case PLDM_SENSOR_DATA_SIZE_UINT32: | 
|  | 173 | maxValue = pdr->max_readable.value_u32; | 
|  | 174 | minValue = pdr->min_readable.value_u32; | 
|  | 175 | hysteresis = pdr->hysteresis.value_u32; | 
|  | 176 | break; | 
|  | 177 | case PLDM_SENSOR_DATA_SIZE_SINT32: | 
|  | 178 | maxValue = pdr->max_readable.value_s32; | 
|  | 179 | minValue = pdr->min_readable.value_s32; | 
|  | 180 | hysteresis = pdr->hysteresis.value_s32; | 
|  | 181 | break; | 
|  | 182 | } | 
|  | 183 |  | 
|  | 184 | bool hasCriticalThresholds = false; | 
|  | 185 | bool hasWarningThresholds = false; | 
|  | 186 | double criticalHigh = std::numeric_limits<double>::quiet_NaN(); | 
|  | 187 | double criticalLow = std::numeric_limits<double>::quiet_NaN(); | 
|  | 188 | double warningHigh = std::numeric_limits<double>::quiet_NaN(); | 
|  | 189 | double warningLow = std::numeric_limits<double>::quiet_NaN(); | 
|  | 190 |  | 
|  | 191 | if (pdr->supported_thresholds.bits.bit0) | 
|  | 192 | { | 
|  | 193 | hasWarningThresholds = true; | 
|  | 194 | switch (pdr->range_field_format) | 
|  | 195 | { | 
|  | 196 | case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
|  | 197 | warningHigh = pdr->warning_high.value_u8; | 
|  | 198 | break; | 
|  | 199 | case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
|  | 200 | warningHigh = pdr->warning_high.value_s8; | 
|  | 201 | break; | 
|  | 202 | case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
|  | 203 | warningHigh = pdr->warning_high.value_u16; | 
|  | 204 | break; | 
|  | 205 | case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
|  | 206 | warningHigh = pdr->warning_high.value_s16; | 
|  | 207 | break; | 
|  | 208 | case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
|  | 209 | warningHigh = pdr->warning_high.value_u32; | 
|  | 210 | break; | 
|  | 211 | case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
|  | 212 | warningHigh = pdr->warning_high.value_s32; | 
|  | 213 | break; | 
|  | 214 | case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
|  | 215 | warningHigh = pdr->warning_high.value_f32; | 
|  | 216 | break; | 
|  | 217 | } | 
|  | 218 | } | 
|  | 219 |  | 
|  | 220 | if (pdr->supported_thresholds.bits.bit3) | 
|  | 221 | { | 
|  | 222 | hasWarningThresholds = true; | 
|  | 223 | switch (pdr->range_field_format) | 
|  | 224 | { | 
|  | 225 | case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
|  | 226 | warningLow = pdr->warning_low.value_u8; | 
|  | 227 | break; | 
|  | 228 | case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
|  | 229 | warningLow = pdr->warning_low.value_s8; | 
|  | 230 | break; | 
|  | 231 | case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
|  | 232 | warningLow = pdr->warning_low.value_u16; | 
|  | 233 | break; | 
|  | 234 | case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
|  | 235 | warningLow = pdr->warning_low.value_s16; | 
|  | 236 | break; | 
|  | 237 | case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
|  | 238 | warningLow = pdr->warning_low.value_u32; | 
|  | 239 | break; | 
|  | 240 | case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
|  | 241 | warningLow = pdr->warning_low.value_s32; | 
|  | 242 | break; | 
|  | 243 | case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
|  | 244 | warningLow = pdr->warning_low.value_f32; | 
|  | 245 | break; | 
|  | 246 | } | 
|  | 247 | } | 
|  | 248 |  | 
|  | 249 | if (pdr->supported_thresholds.bits.bit1) | 
|  | 250 | { | 
|  | 251 | hasCriticalThresholds = true; | 
|  | 252 | switch (pdr->range_field_format) | 
|  | 253 | { | 
|  | 254 | case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
|  | 255 | criticalHigh = pdr->critical_high.value_u8; | 
|  | 256 | break; | 
|  | 257 | case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
|  | 258 | criticalHigh = pdr->critical_high.value_s8; | 
|  | 259 | break; | 
|  | 260 | case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
|  | 261 | criticalHigh = pdr->critical_high.value_u16; | 
|  | 262 | break; | 
|  | 263 | case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
|  | 264 | criticalHigh = pdr->critical_high.value_s16; | 
|  | 265 | break; | 
|  | 266 | case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
|  | 267 | criticalHigh = pdr->critical_high.value_u32; | 
|  | 268 | break; | 
|  | 269 | case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
|  | 270 | criticalHigh = pdr->critical_high.value_s32; | 
|  | 271 | break; | 
|  | 272 | case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
|  | 273 | criticalHigh = pdr->critical_high.value_f32; | 
|  | 274 | break; | 
|  | 275 | } | 
|  | 276 | } | 
|  | 277 |  | 
|  | 278 | if (pdr->supported_thresholds.bits.bit4) | 
|  | 279 | { | 
|  | 280 | hasCriticalThresholds = true; | 
|  | 281 | switch (pdr->range_field_format) | 
|  | 282 | { | 
|  | 283 | case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
|  | 284 | criticalLow = pdr->critical_low.value_u8; | 
|  | 285 | break; | 
|  | 286 | case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
|  | 287 | criticalLow = pdr->critical_low.value_s8; | 
|  | 288 | break; | 
|  | 289 | case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
|  | 290 | criticalLow = pdr->critical_low.value_u16; | 
|  | 291 | break; | 
|  | 292 | case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
|  | 293 | criticalLow = pdr->critical_low.value_s16; | 
|  | 294 | break; | 
|  | 295 | case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
|  | 296 | criticalLow = pdr->critical_low.value_u32; | 
|  | 297 | break; | 
|  | 298 | case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
|  | 299 | criticalLow = pdr->critical_low.value_s32; | 
|  | 300 | break; | 
|  | 301 | case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
|  | 302 | criticalLow = pdr->critical_low.value_f32; | 
|  | 303 | break; | 
|  | 304 | } | 
|  | 305 | } | 
|  | 306 |  | 
|  | 307 | resolution = pdr->resolution; | 
|  | 308 | offset = pdr->offset; | 
|  | 309 | baseUnitModifier = pdr->unit_modifier; | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 310 | timeStamp = 0; | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 311 |  | 
|  | 312 | /** | 
|  | 313 | * DEFAULT_SENSOR_UPDATER_INTERVAL is in milliseconds | 
|  | 314 | * updateTime is in microseconds | 
|  | 315 | */ | 
|  | 316 | updateTime = static_cast<uint64_t>(DEFAULT_SENSOR_UPDATER_INTERVAL * 1000); | 
|  | 317 | if (!std::isnan(pdr->update_interval)) | 
|  | 318 | { | 
|  | 319 | updateTime = pdr->update_interval * 1000000; | 
|  | 320 | } | 
|  | 321 |  | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 322 | if (!useMetricInterface) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 323 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 324 | try | 
|  | 325 | { | 
|  | 326 | valueIntf = std::make_unique<ValueIntf>(bus, path.c_str()); | 
|  | 327 | } | 
|  | 328 | catch (const sdbusplus::exception_t& e) | 
|  | 329 | { | 
|  | 330 | lg2::error( | 
|  | 331 | "Failed to create Value interface for numeric sensor {PATH} error - {ERROR}", | 
|  | 332 | "PATH", path, "ERROR", e); | 
|  | 333 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 334 | InvalidArgument(); | 
|  | 335 | } | 
|  | 336 | valueIntf->maxValue(unitModifier(conversionFormula(maxValue))); | 
|  | 337 | valueIntf->minValue(unitModifier(conversionFormula(minValue))); | 
|  | 338 | valueIntf->unit(sensorUnit); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 339 | } | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 340 | else | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 341 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 342 | try | 
|  | 343 | { | 
|  | 344 | metricIntf = std::make_unique<MetricIntf>(bus, path.c_str()); | 
|  | 345 | } | 
|  | 346 | catch (const sdbusplus::exception_t& e) | 
|  | 347 | { | 
|  | 348 | lg2::error( | 
|  | 349 | "Failed to create Metric interface for numeric sensor {PATH} error - {ERROR}", | 
|  | 350 | "PATH", path, "ERROR", e); | 
|  | 351 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 352 | InvalidArgument(); | 
|  | 353 | } | 
|  | 354 | metricIntf->maxValue(unitModifier(conversionFormula(maxValue))); | 
|  | 355 | metricIntf->minValue(unitModifier(conversionFormula(minValue))); | 
|  | 356 | metricIntf->unit(metricUnit); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 357 | } | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 358 |  | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 359 | hysteresis = unitModifier(conversionFormula(hysteresis)); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 360 |  | 
| Chau Ly | d197f09 | 2023-11-06 07:29:06 +0000 | [diff] [blame] | 361 | if (!createInventoryPath(associationPath, sensorName, pdr->entity_type, | 
|  | 362 | pdr->entity_instance_num, pdr->container_id)) | 
|  | 363 | { | 
|  | 364 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 365 | } | 
|  | 366 |  | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 367 | try | 
|  | 368 | { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 369 | availabilityIntf = | 
|  | 370 | std::make_unique<AvailabilityIntf>(bus, path.c_str()); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 371 | } | 
|  | 372 | catch (const sdbusplus::exception_t& e) | 
|  | 373 | { | 
|  | 374 | lg2::error( | 
|  | 375 | "Failed to create Availability interface for numeric sensor {PATH} error - {ERROR}", | 
|  | 376 | "PATH", path, "ERROR", e); | 
|  | 377 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 378 | } | 
|  | 379 | availabilityIntf->available(true); | 
|  | 380 |  | 
|  | 381 | try | 
|  | 382 | { | 
|  | 383 | operationalStatusIntf = | 
|  | 384 | std::make_unique<OperationalStatusIntf>(bus, path.c_str()); | 
|  | 385 | } | 
|  | 386 | catch (const sdbusplus::exception_t& e) | 
|  | 387 | { | 
|  | 388 | lg2::error( | 
|  | 389 | "Failed to create Operation status interface for numeric sensor {PATH} error - {ERROR}", | 
|  | 390 | "PATH", path, "ERROR", e); | 
|  | 391 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 392 | } | 
|  | 393 | operationalStatusIntf->functional(!sensorDisabled); | 
|  | 394 |  | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 395 | if (hasWarningThresholds && !useMetricInterface) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 396 | { | 
|  | 397 | try | 
|  | 398 | { | 
|  | 399 | thresholdWarningIntf = | 
|  | 400 | std::make_unique<ThresholdWarningIntf>(bus, path.c_str()); | 
|  | 401 | } | 
|  | 402 | catch (const sdbusplus::exception_t& e) | 
|  | 403 | { | 
|  | 404 | lg2::error( | 
|  | 405 | "Failed to create Threshold warning interface for numeric sensor {PATH} error - {ERROR}", | 
|  | 406 | "PATH", path, "ERROR", e); | 
|  | 407 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 408 | InvalidArgument(); | 
|  | 409 | } | 
|  | 410 | thresholdWarningIntf->warningHigh(unitModifier(warningHigh)); | 
|  | 411 | thresholdWarningIntf->warningLow(unitModifier(warningLow)); | 
|  | 412 | } | 
|  | 413 |  | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 414 | if (hasCriticalThresholds && !useMetricInterface) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 415 | { | 
|  | 416 | try | 
|  | 417 | { | 
|  | 418 | thresholdCriticalIntf = | 
|  | 419 | std::make_unique<ThresholdCriticalIntf>(bus, path.c_str()); | 
|  | 420 | } | 
|  | 421 | catch (const sdbusplus::exception_t& e) | 
|  | 422 | { | 
|  | 423 | lg2::error( | 
|  | 424 | "Failed to create Threshold critical interface for numeric sensor {PATH} error - {ERROR}", | 
|  | 425 | "PATH", path, "ERROR", e); | 
|  | 426 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 427 | InvalidArgument(); | 
|  | 428 | } | 
|  | 429 | thresholdCriticalIntf->criticalHigh(unitModifier(criticalHigh)); | 
|  | 430 | thresholdCriticalIntf->criticalLow(unitModifier(criticalLow)); | 
|  | 431 | } | 
|  | 432 | } | 
|  | 433 |  | 
|  | 434 | NumericSensor::NumericSensor( | 
|  | 435 | const pldm_tid_t tid, const bool sensorDisabled, | 
|  | 436 | std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr, | 
|  | 437 | std::string& sensorName, std::string& associationPath) : | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 438 | tid(tid), sensorName(sensorName) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 439 | { | 
|  | 440 | if (!pdr) | 
|  | 441 | { | 
|  | 442 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 443 | } | 
|  | 444 |  | 
|  | 445 | sensorId = pdr->sensor_id; | 
|  | 446 | std::string path; | 
|  | 447 | SensorUnit sensorUnit = SensorUnit::DegreesC; | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 448 | MetricUnit metricUnit = MetricUnit::Count; | 
|  | 449 | useMetricInterface = false; | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 450 |  | 
|  | 451 | switch (pdr->base_unit) | 
|  | 452 | { | 
|  | 453 | case PLDM_SENSOR_UNIT_DEGRESS_C: | 
|  | 454 | sensorNameSpace = "/xyz/openbmc_project/sensors/temperature/"; | 
|  | 455 | sensorUnit = SensorUnit::DegreesC; | 
|  | 456 | break; | 
|  | 457 | case PLDM_SENSOR_UNIT_VOLTS: | 
|  | 458 | sensorNameSpace = "/xyz/openbmc_project/sensors/voltage/"; | 
|  | 459 | sensorUnit = SensorUnit::Volts; | 
|  | 460 | break; | 
|  | 461 | case PLDM_SENSOR_UNIT_AMPS: | 
|  | 462 | sensorNameSpace = "/xyz/openbmc_project/sensors/current/"; | 
|  | 463 | sensorUnit = SensorUnit::Amperes; | 
|  | 464 | break; | 
|  | 465 | case PLDM_SENSOR_UNIT_RPM: | 
|  | 466 | sensorNameSpace = "/xyz/openbmc_project/sensors/fan_pwm/"; | 
|  | 467 | sensorUnit = SensorUnit::RPMS; | 
|  | 468 | break; | 
|  | 469 | case PLDM_SENSOR_UNIT_WATTS: | 
|  | 470 | sensorNameSpace = "/xyz/openbmc_project/sensors/power/"; | 
|  | 471 | sensorUnit = SensorUnit::Watts; | 
|  | 472 | break; | 
|  | 473 | case PLDM_SENSOR_UNIT_JOULES: | 
|  | 474 | sensorNameSpace = "/xyz/openbmc_project/sensors/energy/"; | 
|  | 475 | sensorUnit = SensorUnit::Joules; | 
|  | 476 | break; | 
|  | 477 | case PLDM_SENSOR_UNIT_PERCENTAGE: | 
|  | 478 | sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/"; | 
|  | 479 | sensorUnit = SensorUnit::Percent; | 
|  | 480 | break; | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 481 | case PLDM_SENSOR_UNIT_COUNTS: | 
|  | 482 | case PLDM_SENSOR_UNIT_CORRECTED_ERRORS: | 
|  | 483 | case PLDM_SENSOR_UNIT_UNCORRECTABLE_ERRORS: | 
|  | 484 | sensorNameSpace = "/xyz/openbmc_project/metric/count/"; | 
|  | 485 | useMetricInterface = true; | 
|  | 486 | break; | 
|  | 487 | case PLDM_SENSOR_UNIT_OEMUNIT: | 
|  | 488 | sensorNameSpace = "/xyz/openbmc_project/metric/oem/"; | 
|  | 489 | useMetricInterface = true; | 
|  | 490 | break; | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 491 | default: | 
|  | 492 | lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME", | 
|  | 493 | sensorName, "UNIT", pdr->base_unit); | 
|  | 494 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 495 | InvalidArgument(); | 
|  | 496 | break; | 
|  | 497 | } | 
|  | 498 |  | 
|  | 499 | path = sensorNameSpace + sensorName; | 
|  | 500 | try | 
|  | 501 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 502 | std::string tmp{}; | 
|  | 503 | std::string interface = SENSOR_VALUE_INTF; | 
|  | 504 | if (useMetricInterface) | 
|  | 505 | { | 
|  | 506 | interface = METRIC_VALUE_INTF; | 
|  | 507 | } | 
|  | 508 | tmp = pldm::utils::DBusHandler().getService(path.c_str(), | 
|  | 509 | interface.c_str()); | 
|  | 510 |  | 
|  | 511 | if (!tmp.empty()) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 512 | { | 
|  | 513 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 514 | TooManyResources(); | 
|  | 515 | } | 
|  | 516 | } | 
|  | 517 | catch (const std::exception&) | 
|  | 518 | { | 
|  | 519 | /* The sensor object path is not created */ | 
|  | 520 | } | 
|  | 521 |  | 
|  | 522 | auto& bus = pldm::utils::DBusHandler::getBus(); | 
|  | 523 | try | 
|  | 524 | { | 
|  | 525 | associationDefinitionsIntf = | 
|  | 526 | std::make_unique<AssociationDefinitionsInft>(bus, path.c_str()); | 
|  | 527 | } | 
|  | 528 | catch (const sdbusplus::exception_t& e) | 
|  | 529 | { | 
|  | 530 | lg2::error( | 
|  | 531 | "Failed to create Association interface for compact numeric sensor {PATH} error - {ERROR}", | 
|  | 532 | "PATH", path, "ERROR", e); | 
|  | 533 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 534 | } | 
|  | 535 | associationDefinitionsIntf->associations( | 
|  | 536 | {{"chassis", "all_sensors", associationPath.c_str()}}); | 
|  | 537 |  | 
|  | 538 | double maxValue = std::numeric_limits<double>::quiet_NaN(); | 
|  | 539 | double minValue = std::numeric_limits<double>::quiet_NaN(); | 
|  | 540 | bool hasWarningThresholds = false; | 
|  | 541 | bool hasCriticalThresholds = false; | 
|  | 542 | double criticalHigh = std::numeric_limits<double>::quiet_NaN(); | 
|  | 543 | double criticalLow = std::numeric_limits<double>::quiet_NaN(); | 
|  | 544 | double warningHigh = std::numeric_limits<double>::quiet_NaN(); | 
|  | 545 | double warningLow = std::numeric_limits<double>::quiet_NaN(); | 
|  | 546 |  | 
|  | 547 | if (pdr->range_field_support.bits.bit0) | 
|  | 548 | { | 
|  | 549 | hasWarningThresholds = true; | 
|  | 550 | warningHigh = pdr->warning_high; | 
|  | 551 | } | 
|  | 552 | if (pdr->range_field_support.bits.bit1) | 
|  | 553 | { | 
|  | 554 | hasWarningThresholds = true; | 
|  | 555 | warningLow = pdr->warning_low; | 
|  | 556 | } | 
|  | 557 |  | 
|  | 558 | if (pdr->range_field_support.bits.bit2) | 
|  | 559 | { | 
|  | 560 | hasCriticalThresholds = true; | 
|  | 561 | criticalHigh = pdr->critical_high; | 
|  | 562 | } | 
|  | 563 |  | 
|  | 564 | if (pdr->range_field_support.bits.bit3) | 
|  | 565 | { | 
|  | 566 | hasCriticalThresholds = true; | 
|  | 567 | criticalLow = pdr->critical_low; | 
|  | 568 | } | 
|  | 569 |  | 
|  | 570 | resolution = std::numeric_limits<double>::quiet_NaN(); | 
|  | 571 | offset = std::numeric_limits<double>::quiet_NaN(); | 
|  | 572 | baseUnitModifier = pdr->unit_modifier; | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 573 | timeStamp = 0; | 
| Thu Nguyen | 2027ff5 | 2024-10-03 21:58:22 +0000 | [diff] [blame] | 574 | hysteresis = 0; | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 575 |  | 
|  | 576 | /** | 
|  | 577 | * DEFAULT_SENSOR_UPDATER_INTERVAL is in milliseconds | 
|  | 578 | * updateTime is in microseconds | 
|  | 579 | */ | 
|  | 580 | updateTime = static_cast<uint64_t>(DEFAULT_SENSOR_UPDATER_INTERVAL * 1000); | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 581 |  | 
|  | 582 | if (!useMetricInterface) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 583 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 584 | try | 
|  | 585 | { | 
|  | 586 | valueIntf = std::make_unique<ValueIntf>(bus, path.c_str()); | 
|  | 587 | } | 
|  | 588 | catch (const sdbusplus::exception_t& e) | 
|  | 589 | { | 
|  | 590 | lg2::error( | 
|  | 591 | "Failed to create Value interface for compact numeric sensor {PATH} error - {ERROR}", | 
|  | 592 | "PATH", path, "ERROR", e); | 
|  | 593 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 594 | InvalidArgument(); | 
|  | 595 | } | 
|  | 596 | valueIntf->maxValue(unitModifier(conversionFormula(maxValue))); | 
|  | 597 | valueIntf->minValue(unitModifier(conversionFormula(minValue))); | 
|  | 598 | valueIntf->unit(sensorUnit); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 599 | } | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 600 | else | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 601 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 602 | try | 
|  | 603 | { | 
|  | 604 | metricIntf = std::make_unique<MetricIntf>(bus, path.c_str()); | 
|  | 605 | } | 
|  | 606 | catch (const sdbusplus::exception_t& e) | 
|  | 607 | { | 
|  | 608 | lg2::error( | 
|  | 609 | "Failed to create Metric interface for compact numeric sensor {PATH} error - {ERROR}", | 
|  | 610 | "PATH", path, "ERROR", e); | 
|  | 611 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 612 | InvalidArgument(); | 
|  | 613 | } | 
|  | 614 | metricIntf->maxValue(unitModifier(conversionFormula(maxValue))); | 
|  | 615 | metricIntf->minValue(unitModifier(conversionFormula(minValue))); | 
|  | 616 | metricIntf->unit(metricUnit); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 617 | } | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 618 |  | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 619 | hysteresis = unitModifier(conversionFormula(hysteresis)); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 620 |  | 
| Chau Ly | d197f09 | 2023-11-06 07:29:06 +0000 | [diff] [blame] | 621 | if (!createInventoryPath(associationPath, sensorName, pdr->entity_type, | 
|  | 622 | pdr->entity_instance, pdr->container_id)) | 
|  | 623 | { | 
|  | 624 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 625 | } | 
|  | 626 |  | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 627 | try | 
|  | 628 | { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame] | 629 | availabilityIntf = | 
|  | 630 | std::make_unique<AvailabilityIntf>(bus, path.c_str()); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 631 | } | 
|  | 632 | catch (const sdbusplus::exception_t& e) | 
|  | 633 | { | 
|  | 634 | lg2::error( | 
|  | 635 | "Failed to create Availability interface for compact numeric sensor {PATH} error - {ERROR}", | 
|  | 636 | "PATH", path, "ERROR", e); | 
|  | 637 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 638 | } | 
|  | 639 | availabilityIntf->available(true); | 
|  | 640 |  | 
|  | 641 | try | 
|  | 642 | { | 
|  | 643 | operationalStatusIntf = | 
|  | 644 | std::make_unique<OperationalStatusIntf>(bus, path.c_str()); | 
|  | 645 | } | 
|  | 646 | catch (const sdbusplus::exception_t& e) | 
|  | 647 | { | 
|  | 648 | lg2::error( | 
|  | 649 | "Failed to create Operational status interface for compact numeric sensor {PATH} error - {ERROR}", | 
|  | 650 | "PATH", path, "ERROR", e); | 
|  | 651 | throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
|  | 652 | } | 
|  | 653 | operationalStatusIntf->functional(!sensorDisabled); | 
|  | 654 |  | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 655 | if (hasWarningThresholds && !useMetricInterface) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 656 | { | 
|  | 657 | try | 
|  | 658 | { | 
|  | 659 | thresholdWarningIntf = | 
|  | 660 | std::make_unique<ThresholdWarningIntf>(bus, path.c_str()); | 
|  | 661 | } | 
|  | 662 | catch (const sdbusplus::exception_t& e) | 
|  | 663 | { | 
|  | 664 | lg2::error( | 
|  | 665 | "Failed to create Warning threshold interface for compact numeric sensor {PATH} error - {ERROR}", | 
|  | 666 | "PATH", path, "ERROR", e); | 
|  | 667 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 668 | InvalidArgument(); | 
|  | 669 | } | 
|  | 670 | thresholdWarningIntf->warningHigh(unitModifier(warningHigh)); | 
|  | 671 | thresholdWarningIntf->warningLow(unitModifier(warningLow)); | 
|  | 672 | } | 
|  | 673 |  | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 674 | if (hasCriticalThresholds && !useMetricInterface) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 675 | { | 
|  | 676 | try | 
|  | 677 | { | 
|  | 678 | thresholdCriticalIntf = | 
|  | 679 | std::make_unique<ThresholdCriticalIntf>(bus, path.c_str()); | 
|  | 680 | } | 
|  | 681 | catch (const sdbusplus::exception_t& e) | 
|  | 682 | { | 
|  | 683 | lg2::error( | 
|  | 684 | "Failed to create Critical threshold interface for compact numeric sensor {PATH} error - {ERROR}", | 
|  | 685 | "PATH", path, "ERROR", e); | 
|  | 686 | throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
|  | 687 | InvalidArgument(); | 
|  | 688 | } | 
|  | 689 | thresholdCriticalIntf->criticalHigh(unitModifier(criticalHigh)); | 
|  | 690 | thresholdCriticalIntf->criticalLow(unitModifier(criticalLow)); | 
|  | 691 | } | 
|  | 692 | } | 
|  | 693 |  | 
|  | 694 | double NumericSensor::conversionFormula(double value) | 
|  | 695 | { | 
|  | 696 | double convertedValue = value; | 
|  | 697 | convertedValue *= std::isnan(resolution) ? 1 : resolution; | 
|  | 698 | convertedValue += std::isnan(offset) ? 0 : offset; | 
|  | 699 | return convertedValue; | 
|  | 700 | } | 
|  | 701 |  | 
|  | 702 | double NumericSensor::unitModifier(double value) | 
|  | 703 | { | 
|  | 704 | return std::isnan(value) ? value : value * std::pow(10, baseUnitModifier); | 
|  | 705 | } | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 706 |  | 
|  | 707 | void NumericSensor::updateReading(bool available, bool functional, double value) | 
|  | 708 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 709 | if (!availabilityIntf || !operationalStatusIntf || | 
|  | 710 | (!useMetricInterface && !valueIntf) || | 
|  | 711 | (useMetricInterface && !metricIntf)) | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 712 | { | 
|  | 713 | lg2::error( | 
|  | 714 | "Failed to update sensor {NAME} D-Bus interface don't exist.", | 
|  | 715 | "NAME", sensorName); | 
|  | 716 | return; | 
|  | 717 | } | 
|  | 718 | availabilityIntf->available(available); | 
|  | 719 | operationalStatusIntf->functional(functional); | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 720 | double curValue = 0; | 
|  | 721 | if (!useMetricInterface) | 
|  | 722 | { | 
|  | 723 | curValue = valueIntf->value(); | 
|  | 724 | } | 
|  | 725 | else | 
|  | 726 | { | 
|  | 727 | curValue = metricIntf->value(); | 
|  | 728 | } | 
|  | 729 |  | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 730 | double newValue = std::numeric_limits<double>::quiet_NaN(); | 
|  | 731 | if (functional && available) | 
|  | 732 | { | 
|  | 733 | newValue = unitModifier(conversionFormula(value)); | 
|  | 734 | if (newValue != curValue && | 
|  | 735 | (!std::isnan(newValue) || !std::isnan(curValue))) | 
|  | 736 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 737 | if (!useMetricInterface) | 
|  | 738 | { | 
|  | 739 | valueIntf->value(newValue); | 
|  | 740 | updateThresholds(); | 
|  | 741 | } | 
|  | 742 | else | 
|  | 743 | { | 
|  | 744 | metricIntf->value(newValue); | 
|  | 745 | } | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 746 | } | 
|  | 747 | } | 
|  | 748 | else | 
|  | 749 | { | 
|  | 750 | if (newValue != curValue && | 
|  | 751 | (!std::isnan(newValue) || !std::isnan(curValue))) | 
|  | 752 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 753 | if (!useMetricInterface) | 
|  | 754 | { | 
|  | 755 | valueIntf->value(std::numeric_limits<double>::quiet_NaN()); | 
|  | 756 | } | 
|  | 757 | else | 
|  | 758 | { | 
|  | 759 | metricIntf->value(std::numeric_limits<double>::quiet_NaN()); | 
|  | 760 | } | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 761 | } | 
|  | 762 | } | 
|  | 763 | } | 
|  | 764 |  | 
|  | 765 | void NumericSensor::handleErrGetSensorReading() | 
|  | 766 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 767 | if (!operationalStatusIntf || (!useMetricInterface && !valueIntf) || | 
|  | 768 | (useMetricInterface && !metricIntf)) | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 769 | { | 
|  | 770 | lg2::error( | 
|  | 771 | "Failed to update sensor {NAME} D-Bus interfaces don't exist.", | 
|  | 772 | "NAME", sensorName); | 
|  | 773 | return; | 
|  | 774 | } | 
|  | 775 | operationalStatusIntf->functional(false); | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 776 | if (!useMetricInterface) | 
|  | 777 | { | 
|  | 778 | valueIntf->value(std::numeric_limits<double>::quiet_NaN()); | 
|  | 779 | } | 
|  | 780 | else | 
|  | 781 | { | 
|  | 782 | metricIntf->value(std::numeric_limits<double>::quiet_NaN()); | 
|  | 783 | } | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 784 | } | 
|  | 785 |  | 
|  | 786 | bool NumericSensor::checkThreshold(bool alarm, bool direction, double value, | 
|  | 787 | double threshold, double hyst) | 
|  | 788 | { | 
|  | 789 | if (direction) | 
|  | 790 | { | 
|  | 791 | if (value >= threshold) | 
|  | 792 | { | 
|  | 793 | return true; | 
|  | 794 | } | 
|  | 795 | if (value < (threshold - hyst)) | 
|  | 796 | { | 
|  | 797 | return false; | 
|  | 798 | } | 
|  | 799 | } | 
|  | 800 | else | 
|  | 801 | { | 
|  | 802 | if (value <= threshold) | 
|  | 803 | { | 
|  | 804 | return true; | 
|  | 805 | } | 
|  | 806 | if (value > (threshold + hyst)) | 
|  | 807 | { | 
|  | 808 | return false; | 
|  | 809 | } | 
|  | 810 | } | 
|  | 811 | return alarm; | 
|  | 812 | } | 
|  | 813 |  | 
|  | 814 | void NumericSensor::updateThresholds() | 
|  | 815 | { | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 816 | double value = std::numeric_limits<double>::quiet_NaN(); | 
|  | 817 |  | 
|  | 818 | if ((!useMetricInterface && !valueIntf) || | 
|  | 819 | (useMetricInterface && !metricIntf)) | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 820 | { | 
|  | 821 | lg2::error( | 
|  | 822 | "Failed to update thresholds sensor {NAME} D-Bus interfaces don't exist.", | 
|  | 823 | "NAME", sensorName); | 
|  | 824 | return; | 
|  | 825 | } | 
| Thu Nguyen | 6d615f1 | 2024-04-24 05:02:03 +0000 | [diff] [blame] | 826 | if (!useMetricInterface) | 
|  | 827 | { | 
|  | 828 | value = valueIntf->value(); | 
|  | 829 | } | 
|  | 830 | else | 
|  | 831 | { | 
|  | 832 | value = metricIntf->value(); | 
|  | 833 | } | 
| Gilbert Chen | eac61a4 | 2022-02-23 20:56:19 +0000 | [diff] [blame] | 834 | if (thresholdWarningIntf && | 
|  | 835 | !std::isnan(thresholdWarningIntf->warningHigh())) | 
|  | 836 | { | 
|  | 837 | auto threshold = thresholdWarningIntf->warningHigh(); | 
|  | 838 | auto alarm = thresholdWarningIntf->warningAlarmHigh(); | 
|  | 839 | auto newAlarm = | 
|  | 840 | checkThreshold(alarm, true, value, threshold, hysteresis); | 
|  | 841 | if (alarm != newAlarm) | 
|  | 842 | { | 
|  | 843 | thresholdWarningIntf->warningAlarmHigh(newAlarm); | 
|  | 844 | if (newAlarm) | 
|  | 845 | { | 
|  | 846 | thresholdWarningIntf->warningHighAlarmAsserted(value); | 
|  | 847 | } | 
|  | 848 | else | 
|  | 849 | { | 
|  | 850 | thresholdWarningIntf->warningHighAlarmDeasserted(value); | 
|  | 851 | } | 
|  | 852 | } | 
|  | 853 | } | 
|  | 854 |  | 
|  | 855 | if (thresholdWarningIntf && !std::isnan(thresholdWarningIntf->warningLow())) | 
|  | 856 | { | 
|  | 857 | auto threshold = thresholdWarningIntf->warningLow(); | 
|  | 858 | auto alarm = thresholdWarningIntf->warningAlarmLow(); | 
|  | 859 | auto newAlarm = | 
|  | 860 | checkThreshold(alarm, false, value, threshold, hysteresis); | 
|  | 861 | if (alarm != newAlarm) | 
|  | 862 | { | 
|  | 863 | thresholdWarningIntf->warningAlarmLow(newAlarm); | 
|  | 864 | if (newAlarm) | 
|  | 865 | { | 
|  | 866 | thresholdWarningIntf->warningLowAlarmAsserted(value); | 
|  | 867 | } | 
|  | 868 | else | 
|  | 869 | { | 
|  | 870 | thresholdWarningIntf->warningLowAlarmDeasserted(value); | 
|  | 871 | } | 
|  | 872 | } | 
|  | 873 | } | 
|  | 874 |  | 
|  | 875 | if (thresholdCriticalIntf && | 
|  | 876 | !std::isnan(thresholdCriticalIntf->criticalHigh())) | 
|  | 877 | { | 
|  | 878 | auto threshold = thresholdCriticalIntf->criticalHigh(); | 
|  | 879 | auto alarm = thresholdCriticalIntf->criticalAlarmHigh(); | 
|  | 880 | auto newAlarm = | 
|  | 881 | checkThreshold(alarm, true, value, threshold, hysteresis); | 
|  | 882 | if (alarm != newAlarm) | 
|  | 883 | { | 
|  | 884 | thresholdCriticalIntf->criticalAlarmHigh(newAlarm); | 
|  | 885 | if (newAlarm) | 
|  | 886 | { | 
|  | 887 | thresholdCriticalIntf->criticalHighAlarmAsserted(value); | 
|  | 888 | } | 
|  | 889 | else | 
|  | 890 | { | 
|  | 891 | thresholdCriticalIntf->criticalHighAlarmDeasserted(value); | 
|  | 892 | } | 
|  | 893 | } | 
|  | 894 | } | 
|  | 895 |  | 
|  | 896 | if (thresholdCriticalIntf && | 
|  | 897 | !std::isnan(thresholdCriticalIntf->criticalLow())) | 
|  | 898 | { | 
|  | 899 | auto threshold = thresholdCriticalIntf->criticalLow(); | 
|  | 900 | auto alarm = thresholdCriticalIntf->criticalAlarmLow(); | 
|  | 901 | auto newAlarm = | 
|  | 902 | checkThreshold(alarm, false, value, threshold, hysteresis); | 
|  | 903 | if (alarm != newAlarm) | 
|  | 904 | { | 
|  | 905 | thresholdCriticalIntf->criticalAlarmLow(newAlarm); | 
|  | 906 | if (newAlarm) | 
|  | 907 | { | 
|  | 908 | thresholdCriticalIntf->criticalLowAlarmAsserted(value); | 
|  | 909 | } | 
|  | 910 | else | 
|  | 911 | { | 
|  | 912 | thresholdCriticalIntf->criticalLowAlarmDeasserted(value); | 
|  | 913 | } | 
|  | 914 | } | 
|  | 915 | } | 
|  | 916 | } | 
| Gilbert Chen | 77e6fe7 | 2024-08-06 09:23:30 +0000 | [diff] [blame] | 917 |  | 
|  | 918 | int NumericSensor::triggerThresholdEvent( | 
|  | 919 | pldm::utils::Level eventType, pldm::utils::Direction direction, | 
|  | 920 | double rawValue, bool newAlarm, bool assert) | 
|  | 921 | { | 
|  | 922 | if (!valueIntf) | 
|  | 923 | { | 
|  | 924 | lg2::error( | 
|  | 925 | "Failed to update thresholds sensor {NAME} D-Bus interfaces don't exist.", | 
|  | 926 | "NAME", sensorName); | 
|  | 927 | return PLDM_ERROR; | 
|  | 928 | } | 
|  | 929 |  | 
|  | 930 | auto value = unitModifier(conversionFormula(rawValue)); | 
|  | 931 | lg2::error( | 
|  | 932 | "triggerThresholdEvent eventType {TID}, direction {SID} value {VAL} newAlarm {PSTATE} assert {ESTATE}", | 
|  | 933 | "TID", eventType, "SID", direction, "VAL", value, "PSTATE", newAlarm, | 
|  | 934 | "ESTATE", assert); | 
|  | 935 |  | 
|  | 936 | switch (eventType) | 
|  | 937 | { | 
|  | 938 | case pldm::utils::Level::WARNING: | 
|  | 939 | { | 
|  | 940 | if (!thresholdWarningIntf) | 
|  | 941 | { | 
|  | 942 | lg2::error( | 
|  | 943 | "Error:Trigger sensor warning event for non warning threshold sensors {NAME}", | 
|  | 944 | "NAME", sensorName); | 
|  | 945 | return PLDM_ERROR; | 
|  | 946 | } | 
|  | 947 | if (direction == pldm::utils::Direction::HIGH && | 
|  | 948 | !std::isnan(thresholdWarningIntf->warningHigh())) | 
|  | 949 | { | 
|  | 950 | auto alarm = thresholdWarningIntf->warningAlarmHigh(); | 
|  | 951 | if (alarm == newAlarm) | 
|  | 952 | { | 
|  | 953 | return PLDM_SUCCESS; | 
|  | 954 | } | 
|  | 955 | thresholdWarningIntf->warningAlarmHigh(newAlarm); | 
|  | 956 | if (assert) | 
|  | 957 | { | 
|  | 958 | thresholdWarningIntf->warningHighAlarmAsserted(value); | 
|  | 959 | } | 
|  | 960 | else | 
|  | 961 | { | 
|  | 962 | thresholdWarningIntf->warningHighAlarmDeasserted(value); | 
|  | 963 | } | 
|  | 964 | } | 
|  | 965 | else if (direction == pldm::utils::Direction::LOW && | 
|  | 966 | !std::isnan(thresholdWarningIntf->warningLow())) | 
|  | 967 | { | 
|  | 968 | auto alarm = thresholdWarningIntf->warningAlarmLow(); | 
|  | 969 | if (alarm == newAlarm) | 
|  | 970 | { | 
|  | 971 | return PLDM_SUCCESS; | 
|  | 972 | } | 
|  | 973 | thresholdWarningIntf->warningAlarmLow(newAlarm); | 
|  | 974 | if (assert) | 
|  | 975 | { | 
|  | 976 | thresholdWarningIntf->warningLowAlarmAsserted(value); | 
|  | 977 | } | 
|  | 978 | else | 
|  | 979 | { | 
|  | 980 | thresholdWarningIntf->warningLowAlarmDeasserted(value); | 
|  | 981 | } | 
|  | 982 | } | 
|  | 983 | break; | 
|  | 984 | } | 
|  | 985 | case pldm::utils::Level::CRITICAL: | 
|  | 986 | { | 
|  | 987 | if (!thresholdCriticalIntf) | 
|  | 988 | { | 
|  | 989 | lg2::error( | 
|  | 990 | "Error:Trigger sensor Critical event for non warning threshold sensors {NAME}", | 
|  | 991 | "NAME", sensorName); | 
|  | 992 | return PLDM_ERROR; | 
|  | 993 | } | 
|  | 994 | if (direction == pldm::utils::Direction::HIGH && | 
|  | 995 | !std::isnan(thresholdCriticalIntf->criticalHigh())) | 
|  | 996 | { | 
|  | 997 | auto alarm = thresholdCriticalIntf->criticalAlarmHigh(); | 
|  | 998 | if (alarm == newAlarm) | 
|  | 999 | { | 
|  | 1000 | return PLDM_SUCCESS; | 
|  | 1001 | } | 
|  | 1002 | thresholdCriticalIntf->criticalAlarmHigh(newAlarm); | 
|  | 1003 | if (assert) | 
|  | 1004 | { | 
|  | 1005 | thresholdCriticalIntf->criticalHighAlarmAsserted(value); | 
|  | 1006 | } | 
|  | 1007 | else | 
|  | 1008 | { | 
|  | 1009 | thresholdCriticalIntf->criticalHighAlarmDeasserted(value); | 
|  | 1010 | } | 
|  | 1011 | } | 
|  | 1012 | else if (direction == pldm::utils::Direction::LOW && | 
|  | 1013 | !std::isnan(thresholdCriticalIntf->criticalLow())) | 
|  | 1014 | { | 
|  | 1015 | auto alarm = thresholdCriticalIntf->criticalAlarmLow(); | 
|  | 1016 | if (alarm == newAlarm) | 
|  | 1017 | { | 
|  | 1018 | return PLDM_SUCCESS; | 
|  | 1019 | } | 
|  | 1020 | thresholdCriticalIntf->criticalAlarmLow(newAlarm); | 
|  | 1021 | if (assert) | 
|  | 1022 | { | 
|  | 1023 | thresholdCriticalIntf->criticalLowAlarmAsserted(value); | 
|  | 1024 | } | 
|  | 1025 | else | 
|  | 1026 | { | 
|  | 1027 | thresholdCriticalIntf->criticalLowAlarmDeasserted(value); | 
|  | 1028 | } | 
|  | 1029 | } | 
|  | 1030 | break; | 
|  | 1031 | } | 
|  | 1032 |  | 
|  | 1033 | default: | 
|  | 1034 | break; | 
|  | 1035 | } | 
|  | 1036 |  | 
|  | 1037 | return PLDM_SUCCESS; | 
|  | 1038 | } | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 1039 | } // namespace platform_mc | 
|  | 1040 | } // namespace pldm |