xref: /openbmc/phosphor-power/phosphor-regulators/src/dbus_sensor.hpp (revision 837ece7cdfb2654da19f91612e064041cb7bcce9)
1 /**
2  * Copyright © 2021 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
18 #include "sensors.hpp"
19 
20 #include <sdbusplus/bus.hpp>
21 #include <sdbusplus/server/object.hpp>
22 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
23 #include <xyz/openbmc_project/Sensor/Value/server.hpp>
24 #include <xyz/openbmc_project/State/Decorator/Availability/server.hpp>
25 #include <xyz/openbmc_project/State/Decorator/OperationalStatus/server.hpp>
26 
27 #include <memory>
28 #include <string>
29 #include <tuple>
30 #include <vector>
31 
32 namespace phosphor::power::regulators
33 {
34 
35 /**
36  * Define simple name for the generated C++ class that implements the
37  * xyz.openbmc_project.Sensor.Value interface.
38  */
39 using ValueInterface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
40 
41 /**
42  * Define simple name for the generated C++ class that implements the
43  * xyz.openbmc_project.State.Decorator.OperationalStatus interface.
44  */
45 using OperationalStatusInterface = sdbusplus::xyz::openbmc_project::State::
46     Decorator::server::OperationalStatus;
47 
48 /**
49  * Define simple name for the generated C++ class that implements the
50  * xyz.openbmc_project.State.Decorator.Availability interface.
51  */
52 using AvailabilityInterface =
53     sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability;
54 
55 /**
56  * Define simple name for the generated C++ class that implements the
57  * xyz.openbmc_project.Association.Definitions interface.
58  */
59 using AssociationDefinitionsInterface =
60     sdbusplus::xyz::openbmc_project::Association::server::Definitions;
61 
62 /**
63  * Define simple name for the sdbusplus object_t class that implements all
64  * the necessary D-Bus interfaces via templates/multiple inheritance.
65  */
66 using DBusSensorObject =
67     sdbusplus::server::object_t<ValueInterface, OperationalStatusInterface,
68                                 AvailabilityInterface,
69                                 AssociationDefinitionsInterface>;
70 
71 /**
72  * Define simple name for the generated C++ enum that implements the
73  * valid sensor Unit values on D-Bus.
74  */
75 using Unit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit;
76 
77 /**
78  * Define simple name for the tuple used to create D-Bus associations.
79  */
80 using AssocationTuple = std::tuple<std::string, std::string, std::string>;
81 
82 /**
83  * Root object path for sensors.
84  */
85 constexpr const char* sensorsObjectPath = "/xyz/openbmc_project/sensors";
86 
87 /**
88  * @class DBusSensor
89  *
90  * This class represents a voltage regulator sensor on D-Bus.
91  *
92  * Each voltage rail in the system may provide multiple types of sensor data,
93  * such as temperature, output voltage, and output current.  A DBusSensor tracks
94  * one of these data types for a voltage rail.
95  */
96 class DBusSensor
97 {
98   public:
99     // Specify which compiler-generated methods we want
100     DBusSensor() = delete;
101     DBusSensor(const DBusSensor&) = delete;
102     DBusSensor(DBusSensor&&) = delete;
103     DBusSensor& operator=(const DBusSensor&) = delete;
104     DBusSensor& operator=(DBusSensor&&) = delete;
105     virtual ~DBusSensor() = default;
106 
107     /**
108      * Constructor.
109      *
110      * @param bus D-Bus bus object
111      * @param name sensor name
112      * @param type sensor type
113      * @param value sensor value
114      * @param rail voltage rail associated with this sensor
115      * @param deviceInventoryPath D-Bus inventory path of the voltage regulator
116      *                            device that produces the rail
117      * @param chassisInventoryPath D-Bus inventory path of the chassis that
118      *                             contains the voltage regulator device
119      */
120     explicit DBusSensor(sdbusplus::bus::bus& bus, const std::string& name,
121                         SensorType type, double value, const std::string& rail,
122                         const std::string& deviceInventoryPath,
123                         const std::string& chassisInventoryPath);
124 
125     /**
126      * Disable this sensor.
127      *
128      * Updates the sensor properties on D-Bus to indicate it is no longer
129      * receiving value updates.
130      *
131      * This method is normally called when the system is being powered off.
132      * Sensors are not read when the system is powered off.
133      */
134     void disable();
135 
136     /**
137      * Return the sensor name.
138      *
139      * @return sensor name
140      */
141     const std::string& getName() const
142     {
143         return name;
144     }
145 
146     /**
147      * Return the voltage regulator rail associated with this sensor.
148      *
149      * @return rail
150      */
151     const std::string& getRail() const
152     {
153         return rail;
154     }
155 
156     /**
157      * Return the sensor type.
158      *
159      * @return sensor type
160      */
161     SensorType getType() const
162     {
163         return type;
164     }
165 
166     /**
167      * Set this sensor to the error state.
168      *
169      * Updates the sensor properties on D-Bus to indicate an error occurred and
170      * the sensor value could not be read.
171      */
172     void setToErrorState();
173 
174     /**
175      * Set the value of this sensor.
176      *
177      * Do not specify the value NaN.  This special value is used internally to
178      * indicate the sensor has been disabled or is in the error state.  Call the
179      * disable() or setToErrorState() method instead so that all affected D-Bus
180      * interfaces are updated correctly.
181      *
182      * @param value new sensor value
183      */
184     void setValue(double value);
185 
186   private:
187     /**
188      * Sensor value update policy.
189      *
190      * Determines whether a new sensor value should replace the current value on
191      * D-Bus.
192      */
193     enum class ValueUpdatePolicy : unsigned char
194     {
195         /**
196          * Hysteresis value update policy.
197          *
198          * The sensor value will only be updated if the new value differs from
199          * the current value by at least the hysteresis amount.  This avoids
200          * constant D-Bus traffic due to insignificant value changes.
201          */
202         hysteresis,
203 
204         /**
205          * Highest value update policy.
206          *
207          * The sensor value will only be updated if the new value is higher than
208          * the current value.
209          *
210          * Some sensors contain the highest value observed by the voltage
211          * regulator, such as the highest temperature or highest output voltage.
212          * The regulator internally calculates this value since it can poll the
213          * value very quickly and can catch transient events.
214          *
215          * When the sensor is read from the regulator, the regulator will often
216          * clear its internal value.  It will begin calculating a new highest
217          * value.  For this reason, the D-Bus sensor value is set to the highest
218          * value that has been read across all monitoring cycles.
219          *
220          * The D-Bus sensor value is cleared when the sensor is disabled.  This
221          * normally occurs when the system is powered off.  Thus, the D-Bus
222          * sensor value is normally the highest value read since the system was
223          * powered on.
224          */
225         highest,
226 
227         /**
228          * Lowest value update policy.
229          *
230          * The sensor value will only be updated if the new value is lower than
231          * the current value.
232          *
233          * Some sensors contain the lowest value observed by the voltage
234          * regulator, such as the lowest output current or lowest output
235          * voltage.  The regulator internally calculates this value since it can
236          * poll the value very quickly and can catch transient events.
237          *
238          * When the sensor is read from the regulator, the regulator will often
239          * clear its internal value.  It will begin calculating a new lowest
240          * value.  For this reason, the D-Bus sensor value is set to the lowest
241          * value that has been read across all monitoring cycles.
242          *
243          * The D-Bus sensor value is cleared when the sensor is disabled.  This
244          * normally occurs when the system is powered off.  Thus, the D-Bus
245          * sensor value is normally the lowest value read since the system was
246          * powered on.
247          */
248         lowest
249     };
250 
251     /**
252      * Get the D-Bus associations to create for this sensor.
253      *
254      * @param deviceInventoryPath D-Bus inventory path of the voltage regulator
255      *                            device that produces the rail
256      * @param chassisInventoryPath D-Bus inventory path of the chassis that
257      *                             contains the voltage regulator device
258      */
259     std::vector<AssocationTuple>
260         getAssociations(const std::string& deviceInventoryPath,
261                         const std::string& chassisInventoryPath);
262 
263     /**
264      * Get sensor properties that are based on the sensor type.
265      *
266      * The properties are returned in output parameters.
267      *
268      * Also initializes some data members whose value is based on the sensor
269      * type.
270      *
271      * @param objectPath returns the object path of this sensor
272      * @param unit returns the D-Bus unit for the sensor value
273      * @param minValue returns the minimum sensor value
274      * @param maxValue returns the maximum sensor value
275      */
276     void getTypeBasedProperties(std::string& objectPath, Unit& unit,
277                                 double& minValue, double& maxValue);
278 
279     /**
280      * Set the sensor value on D-Bus to NaN.
281      */
282     void setValueToNaN();
283 
284     /**
285      * Returns whether to update the sensor value on D-Bus with the specified
286      * new value.
287      *
288      * @param value new sensor value
289      * @return true if value should be updated on D-Bus, false otherwise
290      */
291     bool shouldUpdateValue(double value);
292 
293     /**
294      * D-Bus bus object.
295      */
296     sdbusplus::bus::bus& bus;
297 
298     /**
299      * Sensor name.
300      */
301     std::string name{};
302 
303     /**
304      * Sensor type.
305      */
306     SensorType type;
307 
308     /**
309      * Voltage regulator rail associated with this sensor.
310      */
311     std::string rail{};
312 
313     /**
314      * Sensor value update policy.
315      */
316     ValueUpdatePolicy updatePolicy{ValueUpdatePolicy::hysteresis};
317 
318     /**
319      * Hysteresis value.
320      *
321      * Only used when updatePolicy is hysteresis.
322      */
323     double hysteresis{0.0};
324 
325     /**
326      * sdbusplus object_t class that implements all the necessary D-Bus
327      * interfaces via templates and multiple inheritance.
328      */
329     std::unique_ptr<DBusSensorObject> dbusObject{};
330 };
331 
332 } // namespace phosphor::power::regulators
333