blob: b09bcd49de7f92fa1663d8305d26ff3d42751028 [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
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
Gilbert Chen77e6fe72024-08-06 09:23:30 +0000347 /** @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
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000361 /** @brief Terminus ID which the sensor belongs to */
362 pldm_tid_t tid;
363
364 /** @brief Sensor ID */
365 uint16_t sensorId;
366
Gilbert Cheneac61a42022-02-23 20:56:19 +0000367 /** @brief The time stamp since last getSensorReading command in usec */
368 uint64_t timeStamp;
369
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000370 /** @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
Amithash Prasad98256602024-12-19 14:02:30 -0800379 /** @brief Sensor Unit */
380 SensorUnit sensorUnit;
381
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000382 private:
Gilbert Cheneac61a42022-02-23 20:56:19 +0000383 /**
384 * @brief Check sensor reading if any threshold has been crossed and update
385 * Threshold interfaces accordingly
386 */
387 void updateThresholds();
388
Amithash Prasad98256602024-12-19 14:02:30 -0800389 /**
390 * @brief Update the object units based on the PDR baseUnit
391 */
392 void setSensorUnit(uint8_t baseUnit);
393
Chau Lyd197f092023-11-06 07:29:06 +0000394 /** @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
Thu Nguyen6d615f12024-04-24 05:02:03 +0000409 std::unique_ptr<MetricIntf> metricIntf = nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000410 std::unique_ptr<ValueIntf> valueIntf = nullptr;
411 std::unique_ptr<ThresholdWarningIntf> thresholdWarningIntf = nullptr;
412 std::unique_ptr<ThresholdCriticalIntf> thresholdCriticalIntf = nullptr;
Zoey YJ Chung9a224ae2025-04-11 15:40:42 +0800413 std::unique_ptr<ThresholdHardShutdownIntf> thresholdHardShutdownIntf =
414 nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000415 std::unique_ptr<AvailabilityIntf> availabilityIntf = nullptr;
416 std::unique_ptr<OperationalStatusIntf> operationalStatusIntf = nullptr;
417 std::unique_ptr<AssociationDefinitionsInft> associationDefinitionsIntf =
418 nullptr;
Chau Lyd197f092023-11-06 07:29:06 +0000419 std::unique_ptr<EntityIntf> entityIntf = nullptr;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000420
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;
Thu Nguyen6d615f12024-04-24 05:02:03 +0000433 bool useMetricInterface = false;
Thu Nguyen3c5486d2024-08-01 08:03:08 +0000434};
435} // namespace platform_mc
436} // namespace pldm