| 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 |  | 
 | 18 | NumericSensor::NumericSensor(const pldm_tid_t tid, const bool sensorDisabled, | 
 | 19 |                              std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr, | 
 | 20 |                              std::string& sensorName, | 
 | 21 |                              std::string& associationPath) : | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame^] | 22 |     tid(tid), sensorName(sensorName), isPriority(false) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 23 | { | 
 | 24 |     if (!pdr) | 
 | 25 |     { | 
 | 26 |         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
 | 27 |     } | 
 | 28 |  | 
 | 29 |     sensorId = pdr->sensor_id; | 
 | 30 |     std::string path; | 
 | 31 |     SensorUnit sensorUnit = SensorUnit::DegreesC; | 
 | 32 |  | 
 | 33 |     switch (pdr->base_unit) | 
 | 34 |     { | 
 | 35 |         case PLDM_SENSOR_UNIT_DEGRESS_C: | 
 | 36 |             sensorNameSpace = "/xyz/openbmc_project/sensors/temperature/"; | 
 | 37 |             sensorUnit = SensorUnit::DegreesC; | 
 | 38 |             break; | 
 | 39 |         case PLDM_SENSOR_UNIT_VOLTS: | 
 | 40 |             sensorNameSpace = "/xyz/openbmc_project/sensors/voltage/"; | 
 | 41 |             sensorUnit = SensorUnit::Volts; | 
 | 42 |             break; | 
 | 43 |         case PLDM_SENSOR_UNIT_AMPS: | 
 | 44 |             sensorNameSpace = "/xyz/openbmc_project/sensors/current/"; | 
 | 45 |             sensorUnit = SensorUnit::Amperes; | 
 | 46 |             break; | 
 | 47 |         case PLDM_SENSOR_UNIT_RPM: | 
 | 48 |             sensorNameSpace = "/xyz/openbmc_project/sensors/fan_pwm/"; | 
 | 49 |             sensorUnit = SensorUnit::RPMS; | 
 | 50 |             break; | 
 | 51 |         case PLDM_SENSOR_UNIT_WATTS: | 
 | 52 |             sensorNameSpace = "/xyz/openbmc_project/sensors/power/"; | 
 | 53 |             sensorUnit = SensorUnit::Watts; | 
 | 54 |             break; | 
 | 55 |         case PLDM_SENSOR_UNIT_JOULES: | 
 | 56 |             sensorNameSpace = "/xyz/openbmc_project/sensors/energy/"; | 
 | 57 |             sensorUnit = SensorUnit::Joules; | 
 | 58 |             break; | 
 | 59 |         case PLDM_SENSOR_UNIT_PERCENTAGE: | 
 | 60 |             sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/"; | 
 | 61 |             sensorUnit = SensorUnit::Percent; | 
 | 62 |             break; | 
 | 63 |         default: | 
 | 64 |             lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME", | 
 | 65 |                        sensorName, "UNIT", pdr->base_unit); | 
 | 66 |             throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
 | 67 |                 InvalidArgument(); | 
 | 68 |             break; | 
 | 69 |     } | 
 | 70 |  | 
 | 71 |     path = sensorNameSpace + sensorName; | 
 | 72 |     try | 
 | 73 |     { | 
 | 74 |         auto service = pldm::utils::DBusHandler().getService( | 
 | 75 |             path.c_str(), "xyz.openbmc_project.Sensor.Value"); | 
 | 76 |         if (!service.empty()) | 
 | 77 |         { | 
 | 78 |             throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
 | 79 |                 TooManyResources(); | 
 | 80 |         } | 
 | 81 |     } | 
 | 82 |     catch (const std::exception&) | 
 | 83 |     { | 
 | 84 |         /* The sensor object path is not created */ | 
 | 85 |     } | 
 | 86 |  | 
 | 87 |     auto& bus = pldm::utils::DBusHandler::getBus(); | 
 | 88 |     try | 
 | 89 |     { | 
 | 90 |         associationDefinitionsIntf = | 
 | 91 |             std::make_unique<AssociationDefinitionsInft>(bus, path.c_str()); | 
 | 92 |     } | 
 | 93 |     catch (const sdbusplus::exception_t& e) | 
 | 94 |     { | 
 | 95 |         lg2::error( | 
 | 96 |             "Failed to create association interface for numeric sensor {PATH} error - {ERROR}", | 
 | 97 |             "PATH", path, "ERROR", e); | 
 | 98 |         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
 | 99 |     } | 
 | 100 |  | 
 | 101 |     associationDefinitionsIntf->associations( | 
 | 102 |         {{"chassis", "all_sensors", associationPath}}); | 
 | 103 |  | 
 | 104 |     double maxValue = std::numeric_limits<double>::quiet_NaN(); | 
 | 105 |     double minValue = std::numeric_limits<double>::quiet_NaN(); | 
 | 106 |  | 
 | 107 |     switch (pdr->sensor_data_size) | 
 | 108 |     { | 
 | 109 |         case PLDM_SENSOR_DATA_SIZE_UINT8: | 
 | 110 |             maxValue = pdr->max_readable.value_u8; | 
 | 111 |             minValue = pdr->min_readable.value_u8; | 
 | 112 |             hysteresis = pdr->hysteresis.value_u8; | 
 | 113 |             break; | 
 | 114 |         case PLDM_SENSOR_DATA_SIZE_SINT8: | 
 | 115 |             maxValue = pdr->max_readable.value_s8; | 
 | 116 |             minValue = pdr->min_readable.value_s8; | 
 | 117 |             hysteresis = pdr->hysteresis.value_s8; | 
 | 118 |             break; | 
 | 119 |         case PLDM_SENSOR_DATA_SIZE_UINT16: | 
 | 120 |             maxValue = pdr->max_readable.value_u16; | 
 | 121 |             minValue = pdr->min_readable.value_u16; | 
 | 122 |             hysteresis = pdr->hysteresis.value_u16; | 
 | 123 |             break; | 
 | 124 |         case PLDM_SENSOR_DATA_SIZE_SINT16: | 
 | 125 |             maxValue = pdr->max_readable.value_s16; | 
 | 126 |             minValue = pdr->min_readable.value_s16; | 
 | 127 |             hysteresis = pdr->hysteresis.value_s16; | 
 | 128 |             break; | 
 | 129 |         case PLDM_SENSOR_DATA_SIZE_UINT32: | 
 | 130 |             maxValue = pdr->max_readable.value_u32; | 
 | 131 |             minValue = pdr->min_readable.value_u32; | 
 | 132 |             hysteresis = pdr->hysteresis.value_u32; | 
 | 133 |             break; | 
 | 134 |         case PLDM_SENSOR_DATA_SIZE_SINT32: | 
 | 135 |             maxValue = pdr->max_readable.value_s32; | 
 | 136 |             minValue = pdr->min_readable.value_s32; | 
 | 137 |             hysteresis = pdr->hysteresis.value_s32; | 
 | 138 |             break; | 
 | 139 |     } | 
 | 140 |  | 
 | 141 |     bool hasCriticalThresholds = false; | 
 | 142 |     bool hasWarningThresholds = false; | 
 | 143 |     double criticalHigh = std::numeric_limits<double>::quiet_NaN(); | 
 | 144 |     double criticalLow = std::numeric_limits<double>::quiet_NaN(); | 
 | 145 |     double warningHigh = std::numeric_limits<double>::quiet_NaN(); | 
 | 146 |     double warningLow = std::numeric_limits<double>::quiet_NaN(); | 
 | 147 |  | 
 | 148 |     if (pdr->supported_thresholds.bits.bit0) | 
 | 149 |     { | 
 | 150 |         hasWarningThresholds = true; | 
 | 151 |         switch (pdr->range_field_format) | 
 | 152 |         { | 
 | 153 |             case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
 | 154 |                 warningHigh = pdr->warning_high.value_u8; | 
 | 155 |                 break; | 
 | 156 |             case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
 | 157 |                 warningHigh = pdr->warning_high.value_s8; | 
 | 158 |                 break; | 
 | 159 |             case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
 | 160 |                 warningHigh = pdr->warning_high.value_u16; | 
 | 161 |                 break; | 
 | 162 |             case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
 | 163 |                 warningHigh = pdr->warning_high.value_s16; | 
 | 164 |                 break; | 
 | 165 |             case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
 | 166 |                 warningHigh = pdr->warning_high.value_u32; | 
 | 167 |                 break; | 
 | 168 |             case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
 | 169 |                 warningHigh = pdr->warning_high.value_s32; | 
 | 170 |                 break; | 
 | 171 |             case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
 | 172 |                 warningHigh = pdr->warning_high.value_f32; | 
 | 173 |                 break; | 
 | 174 |         } | 
 | 175 |     } | 
 | 176 |  | 
 | 177 |     if (pdr->supported_thresholds.bits.bit3) | 
 | 178 |     { | 
 | 179 |         hasWarningThresholds = true; | 
 | 180 |         switch (pdr->range_field_format) | 
 | 181 |         { | 
 | 182 |             case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
 | 183 |                 warningLow = pdr->warning_low.value_u8; | 
 | 184 |                 break; | 
 | 185 |             case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
 | 186 |                 warningLow = pdr->warning_low.value_s8; | 
 | 187 |                 break; | 
 | 188 |             case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
 | 189 |                 warningLow = pdr->warning_low.value_u16; | 
 | 190 |                 break; | 
 | 191 |             case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
 | 192 |                 warningLow = pdr->warning_low.value_s16; | 
 | 193 |                 break; | 
 | 194 |             case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
 | 195 |                 warningLow = pdr->warning_low.value_u32; | 
 | 196 |                 break; | 
 | 197 |             case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
 | 198 |                 warningLow = pdr->warning_low.value_s32; | 
 | 199 |                 break; | 
 | 200 |             case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
 | 201 |                 warningLow = pdr->warning_low.value_f32; | 
 | 202 |                 break; | 
 | 203 |         } | 
 | 204 |     } | 
 | 205 |  | 
 | 206 |     if (pdr->supported_thresholds.bits.bit1) | 
 | 207 |     { | 
 | 208 |         hasCriticalThresholds = true; | 
 | 209 |         switch (pdr->range_field_format) | 
 | 210 |         { | 
 | 211 |             case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
 | 212 |                 criticalHigh = pdr->critical_high.value_u8; | 
 | 213 |                 break; | 
 | 214 |             case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
 | 215 |                 criticalHigh = pdr->critical_high.value_s8; | 
 | 216 |                 break; | 
 | 217 |             case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
 | 218 |                 criticalHigh = pdr->critical_high.value_u16; | 
 | 219 |                 break; | 
 | 220 |             case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
 | 221 |                 criticalHigh = pdr->critical_high.value_s16; | 
 | 222 |                 break; | 
 | 223 |             case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
 | 224 |                 criticalHigh = pdr->critical_high.value_u32; | 
 | 225 |                 break; | 
 | 226 |             case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
 | 227 |                 criticalHigh = pdr->critical_high.value_s32; | 
 | 228 |                 break; | 
 | 229 |             case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
 | 230 |                 criticalHigh = pdr->critical_high.value_f32; | 
 | 231 |                 break; | 
 | 232 |         } | 
 | 233 |     } | 
 | 234 |  | 
 | 235 |     if (pdr->supported_thresholds.bits.bit4) | 
 | 236 |     { | 
 | 237 |         hasCriticalThresholds = true; | 
 | 238 |         switch (pdr->range_field_format) | 
 | 239 |         { | 
 | 240 |             case PLDM_RANGE_FIELD_FORMAT_UINT8: | 
 | 241 |                 criticalLow = pdr->critical_low.value_u8; | 
 | 242 |                 break; | 
 | 243 |             case PLDM_RANGE_FIELD_FORMAT_SINT8: | 
 | 244 |                 criticalLow = pdr->critical_low.value_s8; | 
 | 245 |                 break; | 
 | 246 |             case PLDM_RANGE_FIELD_FORMAT_UINT16: | 
 | 247 |                 criticalLow = pdr->critical_low.value_u16; | 
 | 248 |                 break; | 
 | 249 |             case PLDM_RANGE_FIELD_FORMAT_SINT16: | 
 | 250 |                 criticalLow = pdr->critical_low.value_s16; | 
 | 251 |                 break; | 
 | 252 |             case PLDM_RANGE_FIELD_FORMAT_UINT32: | 
 | 253 |                 criticalLow = pdr->critical_low.value_u32; | 
 | 254 |                 break; | 
 | 255 |             case PLDM_RANGE_FIELD_FORMAT_SINT32: | 
 | 256 |                 criticalLow = pdr->critical_low.value_s32; | 
 | 257 |                 break; | 
 | 258 |             case PLDM_RANGE_FIELD_FORMAT_REAL32: | 
 | 259 |                 criticalLow = pdr->critical_low.value_f32; | 
 | 260 |                 break; | 
 | 261 |         } | 
 | 262 |     } | 
 | 263 |  | 
 | 264 |     resolution = pdr->resolution; | 
 | 265 |     offset = pdr->offset; | 
 | 266 |     baseUnitModifier = pdr->unit_modifier; | 
 | 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 |     { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame^] | 296 |         availabilityIntf = | 
 | 297 |             std::make_unique<AvailabilityIntf>(bus, path.c_str()); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 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) : | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame^] | 365 |     tid(tid), sensorName(sensorName), isPriority(false) | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 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 |  | 
 | 482 |     /** | 
 | 483 |      * DEFAULT_SENSOR_UPDATER_INTERVAL is in milliseconds | 
 | 484 |      * updateTime is in microseconds | 
 | 485 |      */ | 
 | 486 |     updateTime = static_cast<uint64_t>(DEFAULT_SENSOR_UPDATER_INTERVAL * 1000); | 
 | 487 |     try | 
 | 488 |     { | 
 | 489 |         valueIntf = std::make_unique<ValueIntf>(bus, path.c_str()); | 
 | 490 |     } | 
 | 491 |     catch (const sdbusplus::exception_t& e) | 
 | 492 |     { | 
 | 493 |         lg2::error( | 
 | 494 |             "Failed to create Value interface for compact numeric sensor {PATH} error - {ERROR}", | 
 | 495 |             "PATH", path, "ERROR", e); | 
 | 496 |         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
 | 497 |     } | 
 | 498 |     valueIntf->maxValue(unitModifier(conversionFormula(maxValue))); | 
 | 499 |     valueIntf->minValue(unitModifier(conversionFormula(minValue))); | 
 | 500 |     hysteresis = unitModifier(conversionFormula(hysteresis)); | 
 | 501 |     valueIntf->unit(sensorUnit); | 
 | 502 |  | 
 | 503 |     try | 
 | 504 |     { | 
| Patrick Williams | 16c2a0a | 2024-08-16 15:20:59 -0400 | [diff] [blame^] | 505 |         availabilityIntf = | 
 | 506 |             std::make_unique<AvailabilityIntf>(bus, path.c_str()); | 
| Thu Nguyen | 3c5486d | 2024-08-01 08:03:08 +0000 | [diff] [blame] | 507 |     } | 
 | 508 |     catch (const sdbusplus::exception_t& e) | 
 | 509 |     { | 
 | 510 |         lg2::error( | 
 | 511 |             "Failed to create Availability interface for compact numeric sensor {PATH} error - {ERROR}", | 
 | 512 |             "PATH", path, "ERROR", e); | 
 | 513 |         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
 | 514 |     } | 
 | 515 |     availabilityIntf->available(true); | 
 | 516 |  | 
 | 517 |     try | 
 | 518 |     { | 
 | 519 |         operationalStatusIntf = | 
 | 520 |             std::make_unique<OperationalStatusIntf>(bus, path.c_str()); | 
 | 521 |     } | 
 | 522 |     catch (const sdbusplus::exception_t& e) | 
 | 523 |     { | 
 | 524 |         lg2::error( | 
 | 525 |             "Failed to create Operational status interface for compact numeric sensor {PATH} error - {ERROR}", | 
 | 526 |             "PATH", path, "ERROR", e); | 
 | 527 |         throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument(); | 
 | 528 |     } | 
 | 529 |     operationalStatusIntf->functional(!sensorDisabled); | 
 | 530 |  | 
 | 531 |     if (hasWarningThresholds) | 
 | 532 |     { | 
 | 533 |         try | 
 | 534 |         { | 
 | 535 |             thresholdWarningIntf = | 
 | 536 |                 std::make_unique<ThresholdWarningIntf>(bus, path.c_str()); | 
 | 537 |         } | 
 | 538 |         catch (const sdbusplus::exception_t& e) | 
 | 539 |         { | 
 | 540 |             lg2::error( | 
 | 541 |                 "Failed to create Warning threshold interface for compact numeric sensor {PATH} error - {ERROR}", | 
 | 542 |                 "PATH", path, "ERROR", e); | 
 | 543 |             throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
 | 544 |                 InvalidArgument(); | 
 | 545 |         } | 
 | 546 |         thresholdWarningIntf->warningHigh(unitModifier(warningHigh)); | 
 | 547 |         thresholdWarningIntf->warningLow(unitModifier(warningLow)); | 
 | 548 |     } | 
 | 549 |  | 
 | 550 |     if (hasCriticalThresholds) | 
 | 551 |     { | 
 | 552 |         try | 
 | 553 |         { | 
 | 554 |             thresholdCriticalIntf = | 
 | 555 |                 std::make_unique<ThresholdCriticalIntf>(bus, path.c_str()); | 
 | 556 |         } | 
 | 557 |         catch (const sdbusplus::exception_t& e) | 
 | 558 |         { | 
 | 559 |             lg2::error( | 
 | 560 |                 "Failed to create Critical threshold interface for compact numeric sensor {PATH} error - {ERROR}", | 
 | 561 |                 "PATH", path, "ERROR", e); | 
 | 562 |             throw sdbusplus::xyz::openbmc_project::Common::Error:: | 
 | 563 |                 InvalidArgument(); | 
 | 564 |         } | 
 | 565 |         thresholdCriticalIntf->criticalHigh(unitModifier(criticalHigh)); | 
 | 566 |         thresholdCriticalIntf->criticalLow(unitModifier(criticalLow)); | 
 | 567 |     } | 
 | 568 | } | 
 | 569 |  | 
 | 570 | double NumericSensor::conversionFormula(double value) | 
 | 571 | { | 
 | 572 |     double convertedValue = value; | 
 | 573 |     convertedValue *= std::isnan(resolution) ? 1 : resolution; | 
 | 574 |     convertedValue += std::isnan(offset) ? 0 : offset; | 
 | 575 |     return convertedValue; | 
 | 576 | } | 
 | 577 |  | 
 | 578 | double NumericSensor::unitModifier(double value) | 
 | 579 | { | 
 | 580 |     return std::isnan(value) ? value : value * std::pow(10, baseUnitModifier); | 
 | 581 | } | 
 | 582 | } // namespace platform_mc | 
 | 583 | } // namespace pldm |