xref: /openbmc/pldm/platform-mc/numeric_sensor.hpp (revision 9a224aeba8c274d8dc5ffd6597fe85acd54dfcd8)
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      */
getThresholdLowerHardShutdownl()203     double getThresholdLowerHardShutdownl()
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 Check if value is over threshold.
216      *
217      *  @param[in] eventType - event level in pldm::utils::Level
218      *  @param[in] direction - direction type in pldm::utils::Direction
219      *  @param[in] rawValue - sensor raw value
220      *  @param[in] newAlarm - trigger alarm true/false
221      *  @param[in] assert - event type asserted/deasserted
222      *
223      *  @return PLDM completion code
224      */
225     int triggerThresholdEvent(pldm::utils::Level eventType,
226                               pldm::utils::Direction direction, double rawValue,
227                               bool newAlarm, bool assert);
228 
229     /** @brief Terminus ID which the sensor belongs to */
230     pldm_tid_t tid;
231 
232     /** @brief Sensor ID */
233     uint16_t sensorId;
234 
235     /** @brief  The time stamp since last getSensorReading command in usec */
236     uint64_t timeStamp;
237 
238     /** @brief  The time of sensor update interval in usec */
239     uint64_t updateTime;
240 
241     /** @brief  sensorName */
242     std::string sensorName;
243 
244     /** @brief  sensorNameSpace */
245     std::string sensorNameSpace;
246 
247     /** @brief Sensor Unit */
248     SensorUnit sensorUnit;
249 
250   private:
251     /**
252      * @brief Check sensor reading if any threshold has been crossed and update
253      * Threshold interfaces accordingly
254      */
255     void updateThresholds();
256 
257     /**
258      * @brief Update the object units based on the PDR baseUnit
259      */
260     void setSensorUnit(uint8_t baseUnit);
261 
262     /** @brief Create the sensor inventory path.
263      *
264      *  @param[in] associationPath - sensor association path
265      *  @param[in] sensorName - sensor name
266      *  @param[in] entityType - sensor PDR entity type
267      *  @param[in] entityInstanceNum - sensor PDR entity instance number
268      *  @param[in] containerId - sensor PDR entity container ID
269      *
270      *  @return True when success otherwise return False
271      */
272     inline bool createInventoryPath(
273         const std::string& associationPath, const std::string& sensorName,
274         const uint16_t entityType, const uint16_t entityInstanceNum,
275         const uint16_t containerId);
276 
277     std::unique_ptr<MetricIntf> metricIntf = nullptr;
278     std::unique_ptr<ValueIntf> valueIntf = nullptr;
279     std::unique_ptr<ThresholdWarningIntf> thresholdWarningIntf = nullptr;
280     std::unique_ptr<ThresholdCriticalIntf> thresholdCriticalIntf = nullptr;
281     std::unique_ptr<ThresholdHardShutdownIntf> thresholdHardShutdownIntf =
282         nullptr;
283     std::unique_ptr<AvailabilityIntf> availabilityIntf = nullptr;
284     std::unique_ptr<OperationalStatusIntf> operationalStatusIntf = nullptr;
285     std::unique_ptr<AssociationDefinitionsInft> associationDefinitionsIntf =
286         nullptr;
287     std::unique_ptr<EntityIntf> entityIntf = nullptr;
288 
289     /** @brief Amount of hysteresis associated with the sensor thresholds */
290     double hysteresis;
291 
292     /** @brief The resolution of sensor in Units */
293     double resolution;
294 
295     /** @brief A constant value that is added in as part of conversion process
296      * of converting a raw sensor reading to Units */
297     double offset;
298 
299     /** @brief A power-of-10 multiplier for baseUnit */
300     int8_t baseUnitModifier;
301     bool useMetricInterface = false;
302 };
303 } // namespace platform_mc
304 } // namespace pldm
305