blob: 9abaf17bb8caa1e138aedb2255b591ad7a9f9cf9 [file] [log] [blame]
Thu Nguyen3c5486d2024-08-01 08:03:08 +00001#pragma once
2
Thu Nguyen3c5486d2024-08-01 08:03:08 +00003#include "common/types.hpp"
Gilbert Chen77e6fe72024-08-06 09:23:30 +00004#include "common/utils.hpp"
Thu Nguyen3c5486d2024-08-01 08:03:08 +00005
Manojkiran Edafe252792025-03-13 19:24:19 +05306#include <libpldm/platform.h>
7#include <libpldm/pldm.h>
8
Thu Nguyen3c5486d2024-08-01 08:03:08 +00009#include <sdbusplus/server/object.hpp>
10#include <xyz/openbmc_project/Association/Definitions/server.hpp>
Chau Lyd197f092023-11-06 07:29:06 +000011#include <xyz/openbmc_project/Inventory/Source/PLDM/Entity/server.hpp>
Thu Nguyen6d615f12024-04-24 05:02:03 +000012#include <xyz/openbmc_project/Metric/Value/server.hpp>
Thu Nguyen3c5486d2024-08-01 08:03:08 +000013#include <xyz/openbmc_project/Sensor/Threshold/Critical/server.hpp>
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +080014#include <xyz/openbmc_project/Sensor/Threshold/HardShutdown/server.hpp>
Thu Nguyen3c5486d2024-08-01 08:03:08 +000015#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
22namespace pldm
23{
24namespace platform_mc
25{
26
Thu Nguyen6d615f12024-04-24 05:02:03 +000027constexpr const char* METRIC_VALUE_INTF = "xyz.openbmc_project.Metric.Value";
28
Thu Nguyen3c5486d2024-08-01 08:03:08 +000029using SensorUnit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit;
30using ValueIntf = sdbusplus::server::object_t<
31 sdbusplus::xyz::openbmc_project::Sensor::server::Value>;
Thu Nguyen6d615f12024-04-24 05:02:03 +000032using MetricUnit = sdbusplus::xyz::openbmc_project::Metric::server::Value::Unit;
33using MetricIntf = sdbusplus::server::object_t<
34 sdbusplus::xyz::openbmc_project::Metric::server::Value>;
Thu Nguyen3c5486d2024-08-01 08:03:08 +000035using ThresholdWarningIntf = sdbusplus::server::object_t<
36 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning>;
37using ThresholdCriticalIntf = sdbusplus::server::object_t<
38 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical>;
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +080039using ThresholdHardShutdownIntf = sdbusplus::server::object_t<
40 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::HardShutdown>;
Thu Nguyen3c5486d2024-08-01 08:03:08 +000041using OperationalStatusIntf =
42 sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::State::
43 Decorator::server::OperationalStatus>;
44using AvailabilityIntf = sdbusplus::server::object_t<
45 sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability>;
46using AssociationDefinitionsInft = sdbusplus::server::object_t<
47 sdbusplus::xyz::openbmc_project::Association::server::Definitions>;
Chau Lyd197f092023-11-06 07:29:06 +000048using EntityIntf = sdbusplus::server::object_t<
49 sdbusplus::xyz::openbmc_project::Inventory::Source::PLDM::server::Entity>;
Thu Nguyen3c5486d2024-08-01 08:03:08 +000050
51/**
52 * @brief NumericSensor
53 *
54 * This class handles sensor reading updated by sensor manager and export
55 * status to D-Bus interface.
56 */
57class NumericSensor
58{
59 public:
60 NumericSensor(const pldm_tid_t tid, const bool sensorDisabled,
61 std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr,
62 std::string& sensorName, std::string& associationPath);
63
64 NumericSensor(const pldm_tid_t tid, const bool sensorDisabled,
65 std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr,
66 std::string& sensorName, std::string& associationPath);
67
Patrick Williams16c2a0a2024-08-16 15:20:59 -040068 ~NumericSensor() {};
Thu Nguyen3c5486d2024-08-01 08:03:08 +000069
Gilbert Cheneac61a42022-02-23 20:56:19 +000070 /** @brief The function called by Sensor Manager to set sensor to
71 * error status.
72 */
73 void handleErrGetSensorReading();
74
75 /** @brief Updating the sensor status to D-Bus interface
76 */
77 void updateReading(bool available, bool functional, double value = 0);
78
Thu Nguyen3c5486d2024-08-01 08:03:08 +000079 /** @brief ConversionFormula is used to convert raw value to the unit
80 * specified in PDR
81 *
82 * @param[in] value - raw value
83 * @return double - converted value
84 */
85 double conversionFormula(double value);
86
87 /** @brief UnitModifier is used to apply the unit modifier specified in PDR
88 *
89 * @param[in] value - raw value
90 * @return double - converted value
91 */
92 double unitModifier(double value);
93
Gilbert Cheneac61a42022-02-23 20:56:19 +000094 /** @brief Check if value is over threshold.
95 *
96 * @param[in] alarm - previous alarm state
97 * @param[in] direction - upper or lower threshold checking
98 * @param[in] value - raw value
99 * @param[in] threshold - threshold value
100 * @param[in] hyst - hysteresis value
101 * @return bool - new alarm state
102 */
103 bool checkThreshold(bool alarm, bool direction, double value,
104 double threshold, double hyst);
105
106 /** @brief Updating the association to D-Bus interface
107 * @param[in] inventoryPath - inventory path of the entity
108 */
109 inline void setInventoryPath(const std::string& inventoryPath)
110 {
111 if (associationDefinitionsIntf)
112 {
113 associationDefinitionsIntf->associations(
114 {{"chassis", "all_sensors", inventoryPath}});
115 }
116 }
117
118 /** @brief Get Upper Critical threshold
119 *
120 * @return double - Upper Critical threshold
121 */
122 double getThresholdUpperCritical()
123 {
124 if (thresholdCriticalIntf)
125 {
126 return thresholdCriticalIntf->criticalHigh();
127 }
128 else
129 {
130 return std::numeric_limits<double>::quiet_NaN();
131 }
132 };
133
134 /** @brief Get Lower Critical threshold
135 *
136 * @return double - Lower Critical threshold
137 */
138 double getThresholdLowerCritical()
139 {
140 if (thresholdCriticalIntf)
141 {
142 return thresholdCriticalIntf->criticalLow();
143 }
144 else
145 {
146 return std::numeric_limits<double>::quiet_NaN();
147 }
148 };
149
150 /** @brief Get Upper Warning threshold
151 *
152 * @return double - Upper Warning threshold
153 */
154 double getThresholdUpperWarning()
155 {
156 if (thresholdWarningIntf)
157 {
158 return thresholdWarningIntf->warningHigh();
159 }
160 else
161 {
162 return std::numeric_limits<double>::quiet_NaN();
163 }
164 };
165
166 /** @brief Get Lower Warning threshold
167 *
168 * @return double - Lower Warning threshold
169 */
170 double getThresholdLowerWarning()
171 {
172 if (thresholdWarningIntf)
173 {
174 return thresholdWarningIntf->warningLow();
175 }
176 else
177 {
178 return std::numeric_limits<double>::quiet_NaN();
179 }
180 };
181
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +0800182 /** @brief Get Upper HardShutdown threshold
183 *
184 * @return double - Upper HardShutdown threshold
185 */
186 double getThresholdUpperHardShutdown()
187 {
188 if (thresholdHardShutdownIntf)
189 {
190 return thresholdHardShutdownIntf->hardShutdownHigh();
191 }
192 else
193 {
194 return std::numeric_limits<double>::quiet_NaN();
195 }
196 };
197
198 /** @brief Get Lower HardShutdown threshold
199 *
200 * @return double - Lower HardShutdown threshold
201 */
Amithash Prasad2480c572025-05-01 15:34:34 -0700202 double getThresholdLowerHardShutdown()
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +0800203 {
204 if (thresholdHardShutdownIntf)
205 {
206 return thresholdHardShutdownIntf->hardShutdownLow();
207 }
208 else
209 {
210 return std::numeric_limits<double>::quiet_NaN();
211 }
212 };
213
Amithash Prasad2480c572025-05-01 15:34:34 -0700214 /** @brief Get threshold given level and direction
215 *
216 * @param[in] level - The threshold level (WARNING/CRITICAL/etc)
217 * @param[in] direction - The threshold direction (HIGH/LOW)
218 *
219 * @return double - The requested threshold.
220 */
221 double getThreshold(pldm::utils::Level level,
222 pldm::utils::Direction direction)
223 {
224 if (direction != pldm::utils::Direction::HIGH &&
225 direction != pldm::utils::Direction::LOW)
226 {
227 return std::numeric_limits<double>::quiet_NaN();
228 }
229 switch (level)
230 {
231 case pldm::utils::Level::WARNING:
232 return direction == pldm::utils::Direction::HIGH
233 ? getThresholdUpperWarning()
234 : getThresholdLowerWarning();
235 case pldm::utils::Level::CRITICAL:
236 return direction == pldm::utils::Direction::HIGH
237 ? getThresholdUpperCritical()
238 : getThresholdLowerCritical();
239 case pldm::utils::Level::HARDSHUTDOWN:
240 return direction == pldm::utils::Direction::HIGH
241 ? getThresholdUpperHardShutdown()
242 : getThresholdLowerHardShutdown();
243 default:
244 break;
245 }
246 return std::numeric_limits<double>::quiet_NaN();
247 }
248
249 /* @brief returns true if the given threshold at level/direction is defined.
250 *
251 * @param[in] level - The threshold level (WARNING/CRITICAL/etc)
252 * @param[in] direction - The threshold direction (HIGH/LOW)
253 *
254 * @return true if the threshold is valid
255 */
256 bool isThresholdValid(pldm::utils::Level level,
257 pldm::utils::Direction direction)
258 {
259 return std::isfinite(getThreshold(level, direction));
260 }
261
262 /* @brief Get the alarm status of the given threshold
263 *
264 * @param[in] level - The threshold level (WARNING/CRITICAL/etc)
265 * @param[in] direction - The threshold direction (HIGH/LOW)
266 *
267 * @return true if the current alarm status is asserted.
268 */
269 bool getThresholdAlarm(pldm::utils::Level level,
270 pldm::utils::Direction direction)
271 {
272 if (!isThresholdValid(level, direction))
273 {
274 return false;
275 }
276 switch (level)
277 {
278 case pldm::utils::Level::WARNING:
279 return direction == pldm::utils::Direction::HIGH
280 ? thresholdWarningIntf->warningAlarmHigh()
281 : thresholdWarningIntf->warningAlarmLow();
282 case pldm::utils::Level::CRITICAL:
283 return direction == pldm::utils::Direction::HIGH
284 ? thresholdCriticalIntf->criticalAlarmHigh()
285 : thresholdCriticalIntf->criticalAlarmLow();
286 case pldm::utils::Level::HARDSHUTDOWN:
287 return direction == pldm::utils::Direction::HIGH
288 ? thresholdHardShutdownIntf->hardShutdownAlarmHigh()
289 : thresholdHardShutdownIntf->hardShutdownAlarmLow();
290 default:
291 break;
292 }
293 return false;
294 }
295
Amithash Prasad79931b62025-05-01 15:34:59 -0700296 /* @brief Returns true if at least one threshold alarm is set
297 *
298 * @return true if at least one threshold alarm is set
299 */
300 bool hasThresholdAlarm();
301
Amithash Prasad2480c572025-05-01 15:34:34 -0700302 /* @brief raises the alarm on the warning threshold
303 *
304 * @param[in] direction - The threshold direction (HIGH/LOW)
305 * @param[in] value - The current numeric sensor reading
306 * @param[in] asserted - true if we want to set the alarm, false
307 * if we want to clear it.
308 *
309 * @return PLDM_SUCCESS or a valid error code.
310 */
311 void setWarningThresholdAlarm(pldm::utils::Direction direction,
312 double value, bool asserted);
313
314 /* @brief raises the alarm on the critical threshold
315 *
316 * @param[in] direction - The threshold direction (HIGH/LOW)
317 * @param[in] value - The current numeric sensor reading
318 * @param[in] asserted - true if we want to set the alarm, false
319 * if we want to clear it.
320 *
321 * @return PLDM_SUCCESS or a valid error code.
322 */
323 void setCriticalThresholdAlarm(pldm::utils::Direction direction,
324 double value, bool asserted);
325
326 /* @brief raises the alarm on the hard-shutdown threshold
327 *
328 * @param[in] direction - The threshold direction (HIGH/LOW)
329 * @param[in] value - The current numeric sensor reading
330 * @param[in] asserted - true if we want to set the alarm, false
331 * if we want to clear it.
332 *
333 * @return PLDM_SUCCESS or a valid error code.
334 */
335 void setHardShutdownThresholdAlarm(pldm::utils::Direction direction,
336 double value, bool asserted);
337
338 /* @brief raises the alarm on the threshold
339 *
340 * @param[in] level - The threshold level (WARNING/CRITICAL/etc)
341 * @param[in] direction - The threshold direction (HIGH/LOW)
342 * @param[in] value - The current numeric sensor reading
343 * @param[in] asserted - true if we want to set the alarm, false
344 * if we want to clear it.
345 *
346 * @return PLDM_SUCCESS or a valid error code.
347 */
348 int setThresholdAlarm(pldm::utils::Level level,
349 pldm::utils::Direction direction, double value,
350 bool asserted);
351
Gilbert Chen77e6fe72024-08-06 09:23:30 +0000352 /** @brief Check if value is over threshold.
353 *
354 * @param[in] eventType - event level in pldm::utils::Level
355 * @param[in] direction - direction type in pldm::utils::Direction
356 * @param[in] rawValue - sensor raw value
357 * @param[in] newAlarm - trigger alarm true/false
358 * @param[in] assert - event type asserted/deasserted
359 *
360 * @return PLDM completion code
361 */
362 int triggerThresholdEvent(pldm::utils::Level eventType,
363 pldm::utils::Direction direction, double rawValue,
364 bool newAlarm, bool assert);
365
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000366 /** @brief Terminus ID which the sensor belongs to */
367 pldm_tid_t tid;
368
369 /** @brief Sensor ID */
370 uint16_t sensorId;
371
Gilbert Cheneac61a42022-02-23 20:56:19 +0000372 /** @brief The time stamp since last getSensorReading command in usec */
373 uint64_t timeStamp;
374
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000375 /** @brief The time of sensor update interval in usec */
376 uint64_t updateTime;
377
378 /** @brief sensorName */
379 std::string sensorName;
380
381 /** @brief sensorNameSpace */
382 std::string sensorNameSpace;
383
Amithash Prasad98256602024-12-19 14:02:30 -0800384 /** @brief Sensor Unit */
385 SensorUnit sensorUnit;
386
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000387 private:
Gilbert Cheneac61a42022-02-23 20:56:19 +0000388 /**
Amithash Prasad79931b62025-05-01 15:34:59 -0700389 * @brief resolve and clear a log entry
390 *
391 * @param[inout] log - dbus path to log entry. The log will be resolve
392 * and the optional reset.
393 */
394 void clearThresholdLog(std::optional<sdbusplus::message::object_path>& log);
395
396 /** @brief create a log entry that all sensor alarms have cleared and is now
397 * operating in the normal operating range.
398 *
399 * @param[in] value - The current sensor value in normal range.
400 */
401 void createNormalRangeLog(double value);
402
403 /**
404 * @brief Create a threshold log for the given level/direction tuple.
405 *
406 * @param[in] level - The level of the threshold.
407 * @param[in] direction - The direction of the threshold.
408 * @param[in] value - The current sensor value.
409 */
410 void createThresholdLog(pldm::utils::Level level,
411 pldm::utils::Direction direction, double value);
412
413 /**
Gilbert Cheneac61a42022-02-23 20:56:19 +0000414 * @brief Check sensor reading if any threshold has been crossed and update
415 * Threshold interfaces accordingly
416 */
417 void updateThresholds();
418
Amithash Prasad98256602024-12-19 14:02:30 -0800419 /**
420 * @brief Update the object units based on the PDR baseUnit
421 */
422 void setSensorUnit(uint8_t baseUnit);
423
Chau Lyd197f092023-11-06 07:29:06 +0000424 /** @brief Create the sensor inventory path.
425 *
426 * @param[in] associationPath - sensor association path
427 * @param[in] sensorName - sensor name
428 * @param[in] entityType - sensor PDR entity type
429 * @param[in] entityInstanceNum - sensor PDR entity instance number
430 * @param[in] containerId - sensor PDR entity container ID
431 *
432 * @return True when success otherwise return False
433 */
434 inline bool createInventoryPath(
435 const std::string& associationPath, const std::string& sensorName,
436 const uint16_t entityType, const uint16_t entityInstanceNum,
437 const uint16_t containerId);
438
Thu Nguyen6d615f12024-04-24 05:02:03 +0000439 std::unique_ptr<MetricIntf> metricIntf = nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000440 std::unique_ptr<ValueIntf> valueIntf = nullptr;
441 std::unique_ptr<ThresholdWarningIntf> thresholdWarningIntf = nullptr;
442 std::unique_ptr<ThresholdCriticalIntf> thresholdCriticalIntf = nullptr;
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +0800443 std::unique_ptr<ThresholdHardShutdownIntf> thresholdHardShutdownIntf =
444 nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000445 std::unique_ptr<AvailabilityIntf> availabilityIntf = nullptr;
446 std::unique_ptr<OperationalStatusIntf> operationalStatusIntf = nullptr;
447 std::unique_ptr<AssociationDefinitionsInft> associationDefinitionsIntf =
448 nullptr;
Chau Lyd197f092023-11-06 07:29:06 +0000449 std::unique_ptr<EntityIntf> entityIntf = nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000450
451 /** @brief Amount of hysteresis associated with the sensor thresholds */
452 double hysteresis;
453
454 /** @brief The resolution of sensor in Units */
455 double resolution;
456
457 /** @brief A constant value that is added in as part of conversion process
458 * of converting a raw sensor reading to Units */
459 double offset;
460
461 /** @brief A power-of-10 multiplier for baseUnit */
462 int8_t baseUnitModifier;
Thu Nguyen6d615f12024-04-24 05:02:03 +0000463 bool useMetricInterface = false;
Amithash Prasad79931b62025-05-01 15:34:59 -0700464
465 /** @brief An internal mapping of thresholds and its associated log
466 * entry. */
467 std::map<std::tuple<pldm::utils::Level, pldm::utils::Direction>,
468 std::optional<sdbusplus::message::object_path>>
469 assertedLog;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000470};
471} // namespace platform_mc
472} // namespace pldm