1 #pragma once 2 3 #include "common/types.hpp" 4 #include "common/utils.hpp" 5 6 #include <libpldm/platform.h> 7 #include <libpldm/pldm.h> 8 9 #include <sdbusplus/server/object.hpp> 10 #include <xyz/openbmc_project/Association/Definitions/server.hpp> 11 #include <xyz/openbmc_project/Inventory/Source/PLDM/Entity/server.hpp> 12 #include <xyz/openbmc_project/Metric/Value/server.hpp> 13 #include <xyz/openbmc_project/Sensor/Threshold/Critical/server.hpp> 14 #include <xyz/openbmc_project/Sensor/Threshold/HardShutdown/server.hpp> 15 #include <xyz/openbmc_project/Sensor/Threshold/Warning/server.hpp> 16 #include <xyz/openbmc_project/Sensor/Value/server.hpp> 17 #include <xyz/openbmc_project/State/Decorator/Availability/server.hpp> 18 #include <xyz/openbmc_project/State/Decorator/OperationalStatus/server.hpp> 19 20 #include <string> 21 22 namespace pldm 23 { 24 namespace platform_mc 25 { 26 27 constexpr const char* SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value"; 28 constexpr const char* METRIC_VALUE_INTF = "xyz.openbmc_project.Metric.Value"; 29 30 using SensorUnit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit; 31 using ValueIntf = sdbusplus::server::object_t< 32 sdbusplus::xyz::openbmc_project::Sensor::server::Value>; 33 using MetricUnit = sdbusplus::xyz::openbmc_project::Metric::server::Value::Unit; 34 using MetricIntf = sdbusplus::server::object_t< 35 sdbusplus::xyz::openbmc_project::Metric::server::Value>; 36 using ThresholdWarningIntf = sdbusplus::server::object_t< 37 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning>; 38 using ThresholdCriticalIntf = sdbusplus::server::object_t< 39 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical>; 40 using ThresholdHardShutdownIntf = sdbusplus::server::object_t< 41 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::HardShutdown>; 42 using OperationalStatusIntf = 43 sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::State:: 44 Decorator::server::OperationalStatus>; 45 using AvailabilityIntf = sdbusplus::server::object_t< 46 sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability>; 47 using AssociationDefinitionsInft = sdbusplus::server::object_t< 48 sdbusplus::xyz::openbmc_project::Association::server::Definitions>; 49 using EntityIntf = sdbusplus::server::object_t< 50 sdbusplus::xyz::openbmc_project::Inventory::Source::PLDM::server::Entity>; 51 52 /** 53 * @brief NumericSensor 54 * 55 * This class handles sensor reading updated by sensor manager and export 56 * status to D-Bus interface. 57 */ 58 class NumericSensor 59 { 60 public: 61 NumericSensor(const pldm_tid_t tid, const bool sensorDisabled, 62 std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr, 63 std::string& sensorName, std::string& associationPath); 64 65 NumericSensor(const pldm_tid_t tid, const bool sensorDisabled, 66 std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr, 67 std::string& sensorName, std::string& associationPath); 68 ~NumericSensor()69 ~NumericSensor() {}; 70 71 /** @brief The function called by Sensor Manager to set sensor to 72 * error status. 73 */ 74 void handleErrGetSensorReading(); 75 76 /** @brief Updating the sensor status to D-Bus interface 77 */ 78 void updateReading(bool available, bool functional, double value = 0); 79 80 /** @brief ConversionFormula is used to convert raw value to the unit 81 * specified in PDR 82 * 83 * @param[in] value - raw value 84 * @return double - converted value 85 */ 86 double conversionFormula(double value); 87 88 /** @brief UnitModifier is used to apply the unit modifier specified in PDR 89 * 90 * @param[in] value - raw value 91 * @return double - converted value 92 */ 93 double unitModifier(double value); 94 95 /** @brief Check if value is over threshold. 96 * 97 * @param[in] alarm - previous alarm state 98 * @param[in] direction - upper or lower threshold checking 99 * @param[in] value - raw value 100 * @param[in] threshold - threshold value 101 * @param[in] hyst - hysteresis value 102 * @return bool - new alarm state 103 */ 104 bool checkThreshold(bool alarm, bool direction, double value, 105 double threshold, double hyst); 106 107 /** @brief Updating the association to D-Bus interface 108 * @param[in] inventoryPath - inventory path of the entity 109 */ setInventoryPath(const std::string & inventoryPath)110 inline void setInventoryPath(const std::string& inventoryPath) 111 { 112 if (associationDefinitionsIntf) 113 { 114 associationDefinitionsIntf->associations( 115 {{"chassis", "all_sensors", inventoryPath}}); 116 } 117 } 118 119 /** @brief Get Upper Critical threshold 120 * 121 * @return double - Upper Critical threshold 122 */ getThresholdUpperCritical()123 double getThresholdUpperCritical() 124 { 125 if (thresholdCriticalIntf) 126 { 127 return thresholdCriticalIntf->criticalHigh(); 128 } 129 else 130 { 131 return std::numeric_limits<double>::quiet_NaN(); 132 } 133 }; 134 135 /** @brief Get Lower Critical threshold 136 * 137 * @return double - Lower Critical threshold 138 */ getThresholdLowerCritical()139 double getThresholdLowerCritical() 140 { 141 if (thresholdCriticalIntf) 142 { 143 return thresholdCriticalIntf->criticalLow(); 144 } 145 else 146 { 147 return std::numeric_limits<double>::quiet_NaN(); 148 } 149 }; 150 151 /** @brief Get Upper Warning threshold 152 * 153 * @return double - Upper Warning threshold 154 */ getThresholdUpperWarning()155 double getThresholdUpperWarning() 156 { 157 if (thresholdWarningIntf) 158 { 159 return thresholdWarningIntf->warningHigh(); 160 } 161 else 162 { 163 return std::numeric_limits<double>::quiet_NaN(); 164 } 165 }; 166 167 /** @brief Get Lower Warning threshold 168 * 169 * @return double - Lower Warning threshold 170 */ getThresholdLowerWarning()171 double getThresholdLowerWarning() 172 { 173 if (thresholdWarningIntf) 174 { 175 return thresholdWarningIntf->warningLow(); 176 } 177 else 178 { 179 return std::numeric_limits<double>::quiet_NaN(); 180 } 181 }; 182 183 /** @brief Get Upper HardShutdown threshold 184 * 185 * @return double - Upper HardShutdown threshold 186 */ getThresholdUpperHardShutdown()187 double getThresholdUpperHardShutdown() 188 { 189 if (thresholdHardShutdownIntf) 190 { 191 return thresholdHardShutdownIntf->hardShutdownHigh(); 192 } 193 else 194 { 195 return std::numeric_limits<double>::quiet_NaN(); 196 } 197 }; 198 199 /** @brief Get Lower HardShutdown threshold 200 * 201 * @return double - Lower HardShutdown threshold 202 */ getThresholdLowerHardShutdown()203 double getThresholdLowerHardShutdown() 204 { 205 if (thresholdHardShutdownIntf) 206 { 207 return thresholdHardShutdownIntf->hardShutdownLow(); 208 } 209 else 210 { 211 return std::numeric_limits<double>::quiet_NaN(); 212 } 213 }; 214 215 /** @brief Get threshold given level and direction 216 * 217 * @param[in] level - The threshold level (WARNING/CRITICAL/etc) 218 * @param[in] direction - The threshold direction (HIGH/LOW) 219 * 220 * @return double - The requested threshold. 221 */ getThreshold(pldm::utils::Level level,pldm::utils::Direction direction)222 double getThreshold(pldm::utils::Level level, 223 pldm::utils::Direction direction) 224 { 225 if (direction != pldm::utils::Direction::HIGH && 226 direction != pldm::utils::Direction::LOW) 227 { 228 return std::numeric_limits<double>::quiet_NaN(); 229 } 230 switch (level) 231 { 232 case pldm::utils::Level::WARNING: 233 return direction == pldm::utils::Direction::HIGH 234 ? getThresholdUpperWarning() 235 : getThresholdLowerWarning(); 236 case pldm::utils::Level::CRITICAL: 237 return direction == pldm::utils::Direction::HIGH 238 ? getThresholdUpperCritical() 239 : getThresholdLowerCritical(); 240 case pldm::utils::Level::HARDSHUTDOWN: 241 return direction == pldm::utils::Direction::HIGH 242 ? getThresholdUpperHardShutdown() 243 : getThresholdLowerHardShutdown(); 244 default: 245 break; 246 } 247 return std::numeric_limits<double>::quiet_NaN(); 248 } 249 250 /* @brief returns true if the given threshold at level/direction is defined. 251 * 252 * @param[in] level - The threshold level (WARNING/CRITICAL/etc) 253 * @param[in] direction - The threshold direction (HIGH/LOW) 254 * 255 * @return true if the threshold is valid 256 */ isThresholdValid(pldm::utils::Level level,pldm::utils::Direction direction)257 bool isThresholdValid(pldm::utils::Level level, 258 pldm::utils::Direction direction) 259 { 260 return std::isfinite(getThreshold(level, direction)); 261 } 262 263 /* @brief Get the alarm status of the given threshold 264 * 265 * @param[in] level - The threshold level (WARNING/CRITICAL/etc) 266 * @param[in] direction - The threshold direction (HIGH/LOW) 267 * 268 * @return true if the current alarm status is asserted. 269 */ getThresholdAlarm(pldm::utils::Level level,pldm::utils::Direction direction)270 bool getThresholdAlarm(pldm::utils::Level level, 271 pldm::utils::Direction direction) 272 { 273 if (!isThresholdValid(level, direction)) 274 { 275 return false; 276 } 277 switch (level) 278 { 279 case pldm::utils::Level::WARNING: 280 return direction == pldm::utils::Direction::HIGH 281 ? thresholdWarningIntf->warningAlarmHigh() 282 : thresholdWarningIntf->warningAlarmLow(); 283 case pldm::utils::Level::CRITICAL: 284 return direction == pldm::utils::Direction::HIGH 285 ? thresholdCriticalIntf->criticalAlarmHigh() 286 : thresholdCriticalIntf->criticalAlarmLow(); 287 case pldm::utils::Level::HARDSHUTDOWN: 288 return direction == pldm::utils::Direction::HIGH 289 ? thresholdHardShutdownIntf->hardShutdownAlarmHigh() 290 : thresholdHardShutdownIntf->hardShutdownAlarmLow(); 291 default: 292 break; 293 } 294 return false; 295 } 296 297 /* @brief raises the alarm on the warning threshold 298 * 299 * @param[in] direction - The threshold direction (HIGH/LOW) 300 * @param[in] value - The current numeric sensor reading 301 * @param[in] asserted - true if we want to set the alarm, false 302 * if we want to clear it. 303 * 304 * @return PLDM_SUCCESS or a valid error code. 305 */ 306 void setWarningThresholdAlarm(pldm::utils::Direction direction, 307 double value, bool asserted); 308 309 /* @brief raises the alarm on the critical threshold 310 * 311 * @param[in] direction - The threshold direction (HIGH/LOW) 312 * @param[in] value - The current numeric sensor reading 313 * @param[in] asserted - true if we want to set the alarm, false 314 * if we want to clear it. 315 * 316 * @return PLDM_SUCCESS or a valid error code. 317 */ 318 void setCriticalThresholdAlarm(pldm::utils::Direction direction, 319 double value, bool asserted); 320 321 /* @brief raises the alarm on the hard-shutdown threshold 322 * 323 * @param[in] direction - The threshold direction (HIGH/LOW) 324 * @param[in] value - The current numeric sensor reading 325 * @param[in] asserted - true if we want to set the alarm, false 326 * if we want to clear it. 327 * 328 * @return PLDM_SUCCESS or a valid error code. 329 */ 330 void setHardShutdownThresholdAlarm(pldm::utils::Direction direction, 331 double value, bool asserted); 332 333 /* @brief raises the alarm on the threshold 334 * 335 * @param[in] level - The threshold level (WARNING/CRITICAL/etc) 336 * @param[in] direction - The threshold direction (HIGH/LOW) 337 * @param[in] value - The current numeric sensor reading 338 * @param[in] asserted - true if we want to set the alarm, false 339 * if we want to clear it. 340 * 341 * @return PLDM_SUCCESS or a valid error code. 342 */ 343 int setThresholdAlarm(pldm::utils::Level level, 344 pldm::utils::Direction direction, double value, 345 bool asserted); 346 347 /** @brief Check if value is over threshold. 348 * 349 * @param[in] eventType - event level in pldm::utils::Level 350 * @param[in] direction - direction type in pldm::utils::Direction 351 * @param[in] rawValue - sensor raw value 352 * @param[in] newAlarm - trigger alarm true/false 353 * @param[in] assert - event type asserted/deasserted 354 * 355 * @return PLDM completion code 356 */ 357 int triggerThresholdEvent(pldm::utils::Level eventType, 358 pldm::utils::Direction direction, double rawValue, 359 bool newAlarm, bool assert); 360 361 /** @brief Terminus ID which the sensor belongs to */ 362 pldm_tid_t tid; 363 364 /** @brief Sensor ID */ 365 uint16_t sensorId; 366 367 /** @brief The time stamp since last getSensorReading command in usec */ 368 uint64_t timeStamp; 369 370 /** @brief The time of sensor update interval in usec */ 371 uint64_t updateTime; 372 373 /** @brief sensorName */ 374 std::string sensorName; 375 376 /** @brief sensorNameSpace */ 377 std::string sensorNameSpace; 378 379 /** @brief Sensor Unit */ 380 SensorUnit sensorUnit; 381 382 private: 383 /** 384 * @brief Check sensor reading if any threshold has been crossed and update 385 * Threshold interfaces accordingly 386 */ 387 void updateThresholds(); 388 389 /** 390 * @brief Update the object units based on the PDR baseUnit 391 */ 392 void setSensorUnit(uint8_t baseUnit); 393 394 /** @brief Create the sensor inventory path. 395 * 396 * @param[in] associationPath - sensor association path 397 * @param[in] sensorName - sensor name 398 * @param[in] entityType - sensor PDR entity type 399 * @param[in] entityInstanceNum - sensor PDR entity instance number 400 * @param[in] containerId - sensor PDR entity container ID 401 * 402 * @return True when success otherwise return False 403 */ 404 inline bool createInventoryPath( 405 const std::string& associationPath, const std::string& sensorName, 406 const uint16_t entityType, const uint16_t entityInstanceNum, 407 const uint16_t containerId); 408 409 std::unique_ptr<MetricIntf> metricIntf = nullptr; 410 std::unique_ptr<ValueIntf> valueIntf = nullptr; 411 std::unique_ptr<ThresholdWarningIntf> thresholdWarningIntf = nullptr; 412 std::unique_ptr<ThresholdCriticalIntf> thresholdCriticalIntf = nullptr; 413 std::unique_ptr<ThresholdHardShutdownIntf> thresholdHardShutdownIntf = 414 nullptr; 415 std::unique_ptr<AvailabilityIntf> availabilityIntf = nullptr; 416 std::unique_ptr<OperationalStatusIntf> operationalStatusIntf = nullptr; 417 std::unique_ptr<AssociationDefinitionsInft> associationDefinitionsIntf = 418 nullptr; 419 std::unique_ptr<EntityIntf> entityIntf = nullptr; 420 421 /** @brief Amount of hysteresis associated with the sensor thresholds */ 422 double hysteresis; 423 424 /** @brief The resolution of sensor in Units */ 425 double resolution; 426 427 /** @brief A constant value that is added in as part of conversion process 428 * of converting a raw sensor reading to Units */ 429 double offset; 430 431 /** @brief A power-of-10 multiplier for baseUnit */ 432 int8_t baseUnitModifier; 433 bool useMetricInterface = false; 434 }; 435 } // namespace platform_mc 436 } // namespace pldm 437