blob: 1ac9b61550a4d613e72b80bb5d0247b79be2ef9c [file] [log] [blame]
Shawn McCarney837ece72021-04-22 13:21:08 -05001/**
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
Shawn McCarney03a25f12021-04-24 17:02:04 -050027#include <chrono>
Shawn McCarney837ece72021-04-22 13:21:08 -050028#include <memory>
29#include <string>
30#include <tuple>
31#include <vector>
32
33namespace phosphor::power::regulators
34{
35
36/**
37 * Define simple name for the generated C++ class that implements the
38 * xyz.openbmc_project.Sensor.Value interface.
39 */
40using ValueInterface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
41
42/**
43 * Define simple name for the generated C++ class that implements the
44 * xyz.openbmc_project.State.Decorator.OperationalStatus interface.
45 */
46using OperationalStatusInterface = sdbusplus::xyz::openbmc_project::State::
47 Decorator::server::OperationalStatus;
48
49/**
50 * Define simple name for the generated C++ class that implements the
51 * xyz.openbmc_project.State.Decorator.Availability interface.
52 */
53using AvailabilityInterface =
54 sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability;
55
56/**
57 * Define simple name for the generated C++ class that implements the
58 * xyz.openbmc_project.Association.Definitions interface.
59 */
60using AssociationDefinitionsInterface =
61 sdbusplus::xyz::openbmc_project::Association::server::Definitions;
62
63/**
64 * Define simple name for the sdbusplus object_t class that implements all
65 * the necessary D-Bus interfaces via templates/multiple inheritance.
66 */
67using DBusSensorObject =
68 sdbusplus::server::object_t<ValueInterface, OperationalStatusInterface,
69 AvailabilityInterface,
70 AssociationDefinitionsInterface>;
71
72/**
73 * Define simple name for the generated C++ enum that implements the
74 * valid sensor Unit values on D-Bus.
75 */
76using Unit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit;
77
78/**
79 * Define simple name for the tuple used to create D-Bus associations.
80 */
81using AssocationTuple = std::tuple<std::string, std::string, std::string>;
82
83/**
84 * Root object path for sensors.
85 */
86constexpr const char* sensorsObjectPath = "/xyz/openbmc_project/sensors";
87
88/**
89 * @class DBusSensor
90 *
91 * This class represents a voltage regulator sensor on D-Bus.
92 *
93 * Each voltage rail in the system may provide multiple types of sensor data,
94 * such as temperature, output voltage, and output current. A DBusSensor tracks
95 * one of these data types for a voltage rail.
96 */
97class DBusSensor
98{
99 public:
100 // Specify which compiler-generated methods we want
101 DBusSensor() = delete;
102 DBusSensor(const DBusSensor&) = delete;
103 DBusSensor(DBusSensor&&) = delete;
104 DBusSensor& operator=(const DBusSensor&) = delete;
105 DBusSensor& operator=(DBusSensor&&) = delete;
106 virtual ~DBusSensor() = default;
107
108 /**
109 * Constructor.
110 *
Shawn McCarney03a25f12021-04-24 17:02:04 -0500111 * Throws an exception if an error occurs.
112 *
Shawn McCarney837ece72021-04-22 13:21:08 -0500113 * @param bus D-Bus bus object
114 * @param name sensor name
115 * @param type sensor type
116 * @param value sensor value
117 * @param rail voltage rail associated with this sensor
118 * @param deviceInventoryPath D-Bus inventory path of the voltage regulator
119 * device that produces the rail
120 * @param chassisInventoryPath D-Bus inventory path of the chassis that
121 * contains the voltage regulator device
122 */
123 explicit DBusSensor(sdbusplus::bus::bus& bus, const std::string& name,
124 SensorType type, double value, const std::string& rail,
125 const std::string& deviceInventoryPath,
126 const std::string& chassisInventoryPath);
127
128 /**
129 * Disable this sensor.
130 *
131 * Updates the sensor properties on D-Bus to indicate it is no longer
132 * receiving value updates.
133 *
134 * This method is normally called when the system is being powered off.
135 * Sensors are not read when the system is powered off.
136 */
137 void disable();
138
139 /**
Shawn McCarney03a25f12021-04-24 17:02:04 -0500140 * Return the last time this sensor was updated.
141 *
142 * @return last update time
143 */
144 const std::chrono::system_clock::time_point& getLastUpdateTime() const
145 {
146 return lastUpdateTime;
147 }
148
149 /**
Shawn McCarney837ece72021-04-22 13:21:08 -0500150 * Return the sensor name.
151 *
152 * @return sensor name
153 */
154 const std::string& getName() const
155 {
156 return name;
157 }
158
159 /**
160 * Return the voltage regulator rail associated with this sensor.
161 *
162 * @return rail
163 */
164 const std::string& getRail() const
165 {
166 return rail;
167 }
168
169 /**
170 * Return the sensor type.
171 *
172 * @return sensor type
173 */
174 SensorType getType() const
175 {
176 return type;
177 }
178
179 /**
180 * Set this sensor to the error state.
181 *
182 * Updates the sensor properties on D-Bus to indicate an error occurred and
183 * the sensor value could not be read.
184 */
185 void setToErrorState();
186
187 /**
188 * Set the value of this sensor.
189 *
190 * Do not specify the value NaN. This special value is used internally to
191 * indicate the sensor has been disabled or is in the error state. Call the
192 * disable() or setToErrorState() method instead so that all affected D-Bus
193 * interfaces are updated correctly.
194 *
195 * @param value new sensor value
196 */
197 void setValue(double value);
198
199 private:
200 /**
201 * Sensor value update policy.
202 *
203 * Determines whether a new sensor value should replace the current value on
204 * D-Bus.
205 */
206 enum class ValueUpdatePolicy : unsigned char
207 {
208 /**
209 * Hysteresis value update policy.
210 *
211 * The sensor value will only be updated if the new value differs from
212 * the current value by at least the hysteresis amount. This avoids
213 * constant D-Bus traffic due to insignificant value changes.
214 */
215 hysteresis,
216
217 /**
218 * Highest value update policy.
219 *
220 * The sensor value will only be updated if the new value is higher than
221 * the current value.
222 *
223 * Some sensors contain the highest value observed by the voltage
224 * regulator, such as the highest temperature or highest output voltage.
225 * The regulator internally calculates this value since it can poll the
226 * value very quickly and can catch transient events.
227 *
228 * When the sensor is read from the regulator, the regulator will often
229 * clear its internal value. It will begin calculating a new highest
230 * value. For this reason, the D-Bus sensor value is set to the highest
231 * value that has been read across all monitoring cycles.
232 *
233 * The D-Bus sensor value is cleared when the sensor is disabled. This
234 * normally occurs when the system is powered off. Thus, the D-Bus
235 * sensor value is normally the highest value read since the system was
236 * powered on.
237 */
238 highest,
239
240 /**
241 * Lowest value update policy.
242 *
243 * The sensor value will only be updated if the new value is lower than
244 * the current value.
245 *
246 * Some sensors contain the lowest value observed by the voltage
247 * regulator, such as the lowest output current or lowest output
248 * voltage. The regulator internally calculates this value since it can
249 * poll the value very quickly and can catch transient events.
250 *
251 * When the sensor is read from the regulator, the regulator will often
252 * clear its internal value. It will begin calculating a new lowest
253 * value. For this reason, the D-Bus sensor value is set to the lowest
254 * value that has been read across all monitoring cycles.
255 *
256 * The D-Bus sensor value is cleared when the sensor is disabled. This
257 * normally occurs when the system is powered off. Thus, the D-Bus
258 * sensor value is normally the lowest value read since the system was
259 * powered on.
260 */
261 lowest
262 };
263
264 /**
265 * Get the D-Bus associations to create for this sensor.
266 *
267 * @param deviceInventoryPath D-Bus inventory path of the voltage regulator
268 * device that produces the rail
269 * @param chassisInventoryPath D-Bus inventory path of the chassis that
270 * contains the voltage regulator device
271 */
272 std::vector<AssocationTuple>
273 getAssociations(const std::string& deviceInventoryPath,
274 const std::string& chassisInventoryPath);
275
276 /**
277 * Get sensor properties that are based on the sensor type.
278 *
279 * The properties are returned in output parameters.
280 *
281 * Also initializes some data members whose value is based on the sensor
282 * type.
283 *
284 * @param objectPath returns the object path of this sensor
285 * @param unit returns the D-Bus unit for the sensor value
286 * @param minValue returns the minimum sensor value
287 * @param maxValue returns the maximum sensor value
288 */
289 void getTypeBasedProperties(std::string& objectPath, Unit& unit,
290 double& minValue, double& maxValue);
291
292 /**
Shawn McCarney03a25f12021-04-24 17:02:04 -0500293 * Set the last time this sensor was updated.
294 */
295 void setLastUpdateTime()
296 {
297 lastUpdateTime = std::chrono::system_clock::now();
298 }
299
300 /**
Shawn McCarney837ece72021-04-22 13:21:08 -0500301 * Set the sensor value on D-Bus to NaN.
302 */
303 void setValueToNaN();
304
305 /**
306 * Returns whether to update the sensor value on D-Bus with the specified
307 * new value.
308 *
309 * @param value new sensor value
310 * @return true if value should be updated on D-Bus, false otherwise
311 */
312 bool shouldUpdateValue(double value);
313
314 /**
315 * D-Bus bus object.
316 */
317 sdbusplus::bus::bus& bus;
318
319 /**
320 * Sensor name.
321 */
322 std::string name{};
323
324 /**
325 * Sensor type.
326 */
327 SensorType type;
328
329 /**
330 * Voltage regulator rail associated with this sensor.
331 */
332 std::string rail{};
333
334 /**
335 * Sensor value update policy.
336 */
337 ValueUpdatePolicy updatePolicy{ValueUpdatePolicy::hysteresis};
338
339 /**
340 * Hysteresis value.
341 *
342 * Only used when updatePolicy is hysteresis.
343 */
344 double hysteresis{0.0};
345
346 /**
347 * sdbusplus object_t class that implements all the necessary D-Bus
348 * interfaces via templates and multiple inheritance.
349 */
350 std::unique_ptr<DBusSensorObject> dbusObject{};
Shawn McCarney03a25f12021-04-24 17:02:04 -0500351
352 /**
353 * Last time this sensor was updated.
354 */
355 std::chrono::system_clock::time_point lastUpdateTime{};
Shawn McCarney837ece72021-04-22 13:21:08 -0500356};
357
358} // namespace phosphor::power::regulators