1 #pragma once
2 
3 #include "libpldm/platform.h"
4 #include "libpldm/pldm.h"
5 
6 #include "common/types.hpp"
7 #include "common/utils.hpp"
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/Warning/server.hpp>
15 #include <xyz/openbmc_project/Sensor/Value/server.hpp>
16 #include <xyz/openbmc_project/State/Decorator/Availability/server.hpp>
17 #include <xyz/openbmc_project/State/Decorator/OperationalStatus/server.hpp>
18 
19 #include <string>
20 
21 namespace pldm
22 {
23 namespace platform_mc
24 {
25 
26 constexpr const char* SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
27 constexpr const char* METRIC_VALUE_INTF = "xyz.openbmc_project.Metric.Value";
28 
29 using SensorUnit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit;
30 using ValueIntf = sdbusplus::server::object_t<
31     sdbusplus::xyz::openbmc_project::Sensor::server::Value>;
32 using MetricUnit = sdbusplus::xyz::openbmc_project::Metric::server::Value::Unit;
33 using MetricIntf = sdbusplus::server::object_t<
34     sdbusplus::xyz::openbmc_project::Metric::server::Value>;
35 using ThresholdWarningIntf = sdbusplus::server::object_t<
36     sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning>;
37 using ThresholdCriticalIntf = sdbusplus::server::object_t<
38     sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Critical>;
39 using OperationalStatusIntf =
40     sdbusplus::server::object_t<sdbusplus::xyz::openbmc_project::State::
41                                     Decorator::server::OperationalStatus>;
42 using AvailabilityIntf = sdbusplus::server::object_t<
43     sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability>;
44 using AssociationDefinitionsInft = sdbusplus::server::object_t<
45     sdbusplus::xyz::openbmc_project::Association::server::Definitions>;
46 using EntityIntf = sdbusplus::server::object_t<
47     sdbusplus::xyz::openbmc_project::Inventory::Source::PLDM::server::Entity>;
48 
49 /**
50  * @brief NumericSensor
51  *
52  * This class handles sensor reading updated by sensor manager and export
53  * status to D-Bus interface.
54  */
55 class NumericSensor
56 {
57   public:
58     NumericSensor(const pldm_tid_t tid, const bool sensorDisabled,
59                   std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr,
60                   std::string& sensorName, std::string& associationPath);
61 
62     NumericSensor(const pldm_tid_t tid, const bool sensorDisabled,
63                   std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr,
64                   std::string& sensorName, std::string& associationPath);
65 
~NumericSensor()66     ~NumericSensor() {};
67 
68     /** @brief The function called by Sensor Manager to set sensor to
69      * error status.
70      */
71     void handleErrGetSensorReading();
72 
73     /** @brief Updating the sensor status to D-Bus interface
74      */
75     void updateReading(bool available, bool functional, double value = 0);
76 
77     /** @brief ConversionFormula is used to convert raw value to the unit
78      * specified in PDR
79      *
80      *  @param[in] value - raw value
81      *  @return double - converted value
82      */
83     double conversionFormula(double value);
84 
85     /** @brief UnitModifier is used to apply the unit modifier specified in PDR
86      *
87      *  @param[in] value - raw value
88      *  @return double - converted value
89      */
90     double unitModifier(double value);
91 
92     /** @brief Check if value is over threshold.
93      *
94      *  @param[in] alarm - previous alarm state
95      *  @param[in] direction - upper or lower threshold checking
96      *  @param[in] value - raw value
97      *  @param[in] threshold - threshold value
98      *  @param[in] hyst - hysteresis value
99      *  @return bool - new alarm state
100      */
101     bool checkThreshold(bool alarm, bool direction, double value,
102                         double threshold, double hyst);
103 
104     /** @brief Updating the association to D-Bus interface
105      *  @param[in] inventoryPath - inventory path of the entity
106      */
setInventoryPath(const std::string & inventoryPath)107     inline void setInventoryPath(const std::string& inventoryPath)
108     {
109         if (associationDefinitionsIntf)
110         {
111             associationDefinitionsIntf->associations(
112                 {{"chassis", "all_sensors", inventoryPath}});
113         }
114     }
115 
116     /** @brief Get Upper Critical threshold
117      *
118      *  @return double - Upper Critical threshold
119      */
getThresholdUpperCritical()120     double getThresholdUpperCritical()
121     {
122         if (thresholdCriticalIntf)
123         {
124             return thresholdCriticalIntf->criticalHigh();
125         }
126         else
127         {
128             return std::numeric_limits<double>::quiet_NaN();
129         }
130     };
131 
132     /** @brief Get Lower Critical threshold
133      *
134      *  @return double - Lower Critical threshold
135      */
getThresholdLowerCritical()136     double getThresholdLowerCritical()
137     {
138         if (thresholdCriticalIntf)
139         {
140             return thresholdCriticalIntf->criticalLow();
141         }
142         else
143         {
144             return std::numeric_limits<double>::quiet_NaN();
145         }
146     };
147 
148     /** @brief Get Upper Warning threshold
149      *
150      *  @return double - Upper Warning threshold
151      */
getThresholdUpperWarning()152     double getThresholdUpperWarning()
153     {
154         if (thresholdWarningIntf)
155         {
156             return thresholdWarningIntf->warningHigh();
157         }
158         else
159         {
160             return std::numeric_limits<double>::quiet_NaN();
161         }
162     };
163 
164     /** @brief Get Lower Warning threshold
165      *
166      *  @return double - Lower Warning threshold
167      */
getThresholdLowerWarning()168     double getThresholdLowerWarning()
169     {
170         if (thresholdWarningIntf)
171         {
172             return thresholdWarningIntf->warningLow();
173         }
174         else
175         {
176             return std::numeric_limits<double>::quiet_NaN();
177         }
178     };
179 
180     /** @brief Check if value is over threshold.
181      *
182      *  @param[in] eventType - event level in pldm::utils::Level
183      *  @param[in] direction - direction type in pldm::utils::Direction
184      *  @param[in] rawValue - sensor raw value
185      *  @param[in] newAlarm - trigger alarm true/false
186      *  @param[in] assert - event type asserted/deasserted
187      *
188      *  @return PLDM completion code
189      */
190     int triggerThresholdEvent(pldm::utils::Level eventType,
191                               pldm::utils::Direction direction, double rawValue,
192                               bool newAlarm, bool assert);
193 
194     /** @brief Terminus ID which the sensor belongs to */
195     pldm_tid_t tid;
196 
197     /** @brief Sensor ID */
198     uint16_t sensorId;
199 
200     /** @brief  The time stamp since last getSensorReading command in usec */
201     uint64_t timeStamp;
202 
203     /** @brief  The time of sensor update interval in usec */
204     uint64_t updateTime;
205 
206     /** @brief  sensorName */
207     std::string sensorName;
208 
209     /** @brief  sensorNameSpace */
210     std::string sensorNameSpace;
211 
212   private:
213     /**
214      * @brief Check sensor reading if any threshold has been crossed and update
215      * Threshold interfaces accordingly
216      */
217     void updateThresholds();
218 
219     /** @brief Create the sensor inventory path.
220      *
221      *  @param[in] associationPath - sensor association path
222      *  @param[in] sensorName - sensor name
223      *  @param[in] entityType - sensor PDR entity type
224      *  @param[in] entityInstanceNum - sensor PDR entity instance number
225      *  @param[in] containerId - sensor PDR entity container ID
226      *
227      *  @return True when success otherwise return False
228      */
229     inline bool createInventoryPath(
230         const std::string& associationPath, const std::string& sensorName,
231         const uint16_t entityType, const uint16_t entityInstanceNum,
232         const uint16_t containerId);
233 
234     std::unique_ptr<MetricIntf> metricIntf = nullptr;
235     std::unique_ptr<ValueIntf> valueIntf = nullptr;
236     std::unique_ptr<ThresholdWarningIntf> thresholdWarningIntf = nullptr;
237     std::unique_ptr<ThresholdCriticalIntf> thresholdCriticalIntf = nullptr;
238     std::unique_ptr<AvailabilityIntf> availabilityIntf = nullptr;
239     std::unique_ptr<OperationalStatusIntf> operationalStatusIntf = nullptr;
240     std::unique_ptr<AssociationDefinitionsInft> associationDefinitionsIntf =
241         nullptr;
242     std::unique_ptr<EntityIntf> entityIntf = nullptr;
243 
244     /** @brief Amount of hysteresis associated with the sensor thresholds */
245     double hysteresis;
246 
247     /** @brief The resolution of sensor in Units */
248     double resolution;
249 
250     /** @brief A constant value that is added in as part of conversion process
251      * of converting a raw sensor reading to Units */
252     double offset;
253 
254     /** @brief A power-of-10 multiplier for baseUnit */
255     int8_t baseUnitModifier;
256     bool useMetricInterface = false;
257 };
258 } // namespace platform_mc
259 } // namespace pldm
260