blob: 3d115b7d021519b3cc39ebd8ff48319dfb0b5654 [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* SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
28constexpr const char* METRIC_VALUE_INTF = "xyz.openbmc_project.Metric.Value";
29
Thu Nguyen3c5486d2024-08-01 08:03:08 +000030using SensorUnit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit;
31using ValueIntf = sdbusplus::server::object_t<
32 sdbusplus::xyz::openbmc_project::Sensor::server::Value>;
Thu Nguyen6d615f12024-04-24 05:02:03 +000033using MetricUnit = sdbusplus::xyz::openbmc_project::Metric::server::Value::Unit;
34using MetricIntf = sdbusplus::server::object_t<
35 sdbusplus::xyz::openbmc_project::Metric::server::Value>;
Thu Nguyen3c5486d2024-08-01 08:03:08 +000036using ThresholdWarningIntf = sdbusplus::server::object_t<
37 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning>;
38using ThresholdCriticalIntf = sdbusplus::server::object_t<
39 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical>;
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +080040using ThresholdHardShutdownIntf = sdbusplus::server::object_t<
41 sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::HardShutdown>;
Thu Nguyen3c5486d2024-08-01 08:03:08 +000042using OperationalStatusIntf =
43 sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::State::
44 Decorator::server::OperationalStatus>;
45using AvailabilityIntf = sdbusplus::server::object_t<
46 sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability>;
47using AssociationDefinitionsInft = sdbusplus::server::object_t<
48 sdbusplus::xyz::openbmc_project::Association::server::Definitions>;
Chau Lyd197f092023-11-06 07:29:06 +000049using EntityIntf = sdbusplus::server::object_t<
50 sdbusplus::xyz::openbmc_project::Inventory::Source::PLDM::server::Entity>;
Thu Nguyen3c5486d2024-08-01 08:03:08 +000051
52/**
53 * @brief NumericSensor
54 *
55 * This class handles sensor reading updated by sensor manager and export
56 * status to D-Bus interface.
57 */
58class 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
Patrick Williams16c2a0a2024-08-16 15:20:59 -040069 ~NumericSensor() {};
Thu Nguyen3c5486d2024-08-01 08:03:08 +000070
Gilbert Cheneac61a42022-02-23 20:56:19 +000071 /** @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
Thu Nguyen3c5486d2024-08-01 08:03:08 +000080 /** @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
Gilbert Cheneac61a42022-02-23 20:56:19 +000095 /** @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 */
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 */
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 */
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 */
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 */
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
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +0800183 /** @brief Get Upper HardShutdown threshold
184 *
185 * @return double - Upper HardShutdown threshold
186 */
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 */
Amithash Prasad2480c572025-05-01 15:34:34 -0700203 double getThresholdLowerHardShutdown()
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +0800204 {
205 if (thresholdHardShutdownIntf)
206 {
207 return thresholdHardShutdownIntf->hardShutdownLow();
208 }
209 else
210 {
211 return std::numeric_limits<double>::quiet_NaN();
212 }
213 };
214
Amithash Prasad2480c572025-05-01 15:34:34 -0700215 /** @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 */
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 */
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 */
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
Amithash Prasad79931b62025-05-01 15:34:59 -0700297 /* @brief Returns true if at least one threshold alarm is set
298 *
299 * @return true if at least one threshold alarm is set
300 */
301 bool hasThresholdAlarm();
302
Amithash Prasad2480c572025-05-01 15:34:34 -0700303 /* @brief raises the alarm on the warning threshold
304 *
305 * @param[in] direction - The threshold direction (HIGH/LOW)
306 * @param[in] value - The current numeric sensor reading
307 * @param[in] asserted - true if we want to set the alarm, false
308 * if we want to clear it.
309 *
310 * @return PLDM_SUCCESS or a valid error code.
311 */
312 void setWarningThresholdAlarm(pldm::utils::Direction direction,
313 double value, bool asserted);
314
315 /* @brief raises the alarm on the critical threshold
316 *
317 * @param[in] direction - The threshold direction (HIGH/LOW)
318 * @param[in] value - The current numeric sensor reading
319 * @param[in] asserted - true if we want to set the alarm, false
320 * if we want to clear it.
321 *
322 * @return PLDM_SUCCESS or a valid error code.
323 */
324 void setCriticalThresholdAlarm(pldm::utils::Direction direction,
325 double value, bool asserted);
326
327 /* @brief raises the alarm on the hard-shutdown threshold
328 *
329 * @param[in] direction - The threshold direction (HIGH/LOW)
330 * @param[in] value - The current numeric sensor reading
331 * @param[in] asserted - true if we want to set the alarm, false
332 * if we want to clear it.
333 *
334 * @return PLDM_SUCCESS or a valid error code.
335 */
336 void setHardShutdownThresholdAlarm(pldm::utils::Direction direction,
337 double value, bool asserted);
338
339 /* @brief raises the alarm on the threshold
340 *
341 * @param[in] level - The threshold level (WARNING/CRITICAL/etc)
342 * @param[in] direction - The threshold direction (HIGH/LOW)
343 * @param[in] value - The current numeric sensor reading
344 * @param[in] asserted - true if we want to set the alarm, false
345 * if we want to clear it.
346 *
347 * @return PLDM_SUCCESS or a valid error code.
348 */
349 int setThresholdAlarm(pldm::utils::Level level,
350 pldm::utils::Direction direction, double value,
351 bool asserted);
352
Gilbert Chen77e6fe72024-08-06 09:23:30 +0000353 /** @brief Check if value is over threshold.
354 *
355 * @param[in] eventType - event level in pldm::utils::Level
356 * @param[in] direction - direction type in pldm::utils::Direction
357 * @param[in] rawValue - sensor raw value
358 * @param[in] newAlarm - trigger alarm true/false
359 * @param[in] assert - event type asserted/deasserted
360 *
361 * @return PLDM completion code
362 */
363 int triggerThresholdEvent(pldm::utils::Level eventType,
364 pldm::utils::Direction direction, double rawValue,
365 bool newAlarm, bool assert);
366
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000367 /** @brief Terminus ID which the sensor belongs to */
368 pldm_tid_t tid;
369
370 /** @brief Sensor ID */
371 uint16_t sensorId;
372
Gilbert Cheneac61a42022-02-23 20:56:19 +0000373 /** @brief The time stamp since last getSensorReading command in usec */
374 uint64_t timeStamp;
375
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000376 /** @brief The time of sensor update interval in usec */
377 uint64_t updateTime;
378
379 /** @brief sensorName */
380 std::string sensorName;
381
382 /** @brief sensorNameSpace */
383 std::string sensorNameSpace;
384
Amithash Prasad98256602024-12-19 14:02:30 -0800385 /** @brief Sensor Unit */
386 SensorUnit sensorUnit;
387
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000388 private:
Gilbert Cheneac61a42022-02-23 20:56:19 +0000389 /**
Amithash Prasad79931b62025-05-01 15:34:59 -0700390 * @brief resolve and clear a log entry
391 *
392 * @param[inout] log - dbus path to log entry. The log will be resolve
393 * and the optional reset.
394 */
395 void clearThresholdLog(std::optional<sdbusplus::message::object_path>& log);
396
397 /** @brief create a log entry that all sensor alarms have cleared and is now
398 * operating in the normal operating range.
399 *
400 * @param[in] value - The current sensor value in normal range.
401 */
402 void createNormalRangeLog(double value);
403
404 /**
405 * @brief Create a threshold log for the given level/direction tuple.
406 *
407 * @param[in] level - The level of the threshold.
408 * @param[in] direction - The direction of the threshold.
409 * @param[in] value - The current sensor value.
410 */
411 void createThresholdLog(pldm::utils::Level level,
412 pldm::utils::Direction direction, double value);
413
414 /**
Gilbert Cheneac61a42022-02-23 20:56:19 +0000415 * @brief Check sensor reading if any threshold has been crossed and update
416 * Threshold interfaces accordingly
417 */
418 void updateThresholds();
419
Amithash Prasad98256602024-12-19 14:02:30 -0800420 /**
421 * @brief Update the object units based on the PDR baseUnit
422 */
423 void setSensorUnit(uint8_t baseUnit);
424
Chau Lyd197f092023-11-06 07:29:06 +0000425 /** @brief Create the sensor inventory path.
426 *
427 * @param[in] associationPath - sensor association path
428 * @param[in] sensorName - sensor name
429 * @param[in] entityType - sensor PDR entity type
430 * @param[in] entityInstanceNum - sensor PDR entity instance number
431 * @param[in] containerId - sensor PDR entity container ID
432 *
433 * @return True when success otherwise return False
434 */
435 inline bool createInventoryPath(
436 const std::string& associationPath, const std::string& sensorName,
437 const uint16_t entityType, const uint16_t entityInstanceNum,
438 const uint16_t containerId);
439
Thu Nguyen6d615f12024-04-24 05:02:03 +0000440 std::unique_ptr<MetricIntf> metricIntf = nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000441 std::unique_ptr<ValueIntf> valueIntf = nullptr;
442 std::unique_ptr<ThresholdWarningIntf> thresholdWarningIntf = nullptr;
443 std::unique_ptr<ThresholdCriticalIntf> thresholdCriticalIntf = nullptr;
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +0800444 std::unique_ptr<ThresholdHardShutdownIntf> thresholdHardShutdownIntf =
445 nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000446 std::unique_ptr<AvailabilityIntf> availabilityIntf = nullptr;
447 std::unique_ptr<OperationalStatusIntf> operationalStatusIntf = nullptr;
448 std::unique_ptr<AssociationDefinitionsInft> associationDefinitionsIntf =
449 nullptr;
Chau Lyd197f092023-11-06 07:29:06 +0000450 std::unique_ptr<EntityIntf> entityIntf = nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000451
452 /** @brief Amount of hysteresis associated with the sensor thresholds */
453 double hysteresis;
454
455 /** @brief The resolution of sensor in Units */
456 double resolution;
457
458 /** @brief A constant value that is added in as part of conversion process
459 * of converting a raw sensor reading to Units */
460 double offset;
461
462 /** @brief A power-of-10 multiplier for baseUnit */
463 int8_t baseUnitModifier;
Thu Nguyen6d615f12024-04-24 05:02:03 +0000464 bool useMetricInterface = false;
Amithash Prasad79931b62025-05-01 15:34:59 -0700465
466 /** @brief An internal mapping of thresholds and its associated log
467 * entry. */
468 std::map<std::tuple<pldm::utils::Level, pldm::utils::Direction>,
469 std::optional<sdbusplus::message::object_path>>
470 assertedLog;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000471};
472} // namespace platform_mc
473} // namespace pldm