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 <chrono> 28 #include <memory> 29 #include <string> 30 #include <tuple> 31 #include <vector> 32 33 namespace 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 */ 40 using 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 */ 46 using 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 */ 53 using 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 */ 60 using 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 */ 67 using 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 */ 76 using 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 */ 81 using AssocationTuple = std::tuple<std::string, std::string, std::string>; 82 83 /** 84 * Root object path for sensors. 85 */ 86 constexpr 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 */ 97 class 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 * 111 * Throws an exception if an error occurs. 112 * 113 * @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_t& 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 /** 140 * 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 /** 150 * 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 /** 293 * Set the last time this sensor was updated. 294 */ 295 void setLastUpdateTime() 296 { 297 lastUpdateTime = std::chrono::system_clock::now(); 298 } 299 300 /** 301 * 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_t& 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{}; 351 352 /** 353 * Last time this sensor was updated. 354 */ 355 std::chrono::system_clock::time_point lastUpdateTime{}; 356 }; 357 358 } // namespace phosphor::power::regulators 359