regulators: Create DBusSensor class
Create the DBusSensor class that represents a voltage regulator sensor
on D-Bus.
Each voltage rail in the system may provide multiple types of sensor
data, such as temperature, output voltage, and output current. A
DBusSensor tracks one of these data types for a voltage rail.
Class supports the following sensor operations:
* Create sensor
* Set sensor value
* Disable sensor (when system is powered off)
* Set sensor to error state (when unable to read value due to I2C error)
* Delete sensor
Note: A different class will implement the ObjectManager interface for
all voltage regulator sensors. That will be in a future commit.
Tested:
* Created a sensor of each supported type (vout, iout, etc.)
* Set the value of a sensor
* Tested update policies: hysteresis, highest, lowest
* Disabled a sensor
* Set a sensor to the error state
* Verified all D-Bus signals emitted
* InterfacesAdded signal emitted with all info when sensor created
* PropertiesChanged signal emitted when sensor properties change
* InterfacesRemoved signal emitted when sensor deleted
* See https://gist.github.com/smccarney/5ae989da1977162ae1a21c208d5302fc
for complete test plan.
Signed-off-by: Shawn McCarney <shawnmm@us.ibm.com>
Change-Id: I655277e6bf0a31a8778a54e87d5864f9951b045e
diff --git a/phosphor-regulators/src/dbus_sensor.hpp b/phosphor-regulators/src/dbus_sensor.hpp
new file mode 100644
index 0000000..4e39c34
--- /dev/null
+++ b/phosphor-regulators/src/dbus_sensor.hpp
@@ -0,0 +1,332 @@
+/**
+ * Copyright © 2021 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include "sensors.hpp"
+
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/server/object.hpp>
+#include <xyz/openbmc_project/Association/Definitions/server.hpp>
+#include <xyz/openbmc_project/Sensor/Value/server.hpp>
+#include <xyz/openbmc_project/State/Decorator/Availability/server.hpp>
+#include <xyz/openbmc_project/State/Decorator/OperationalStatus/server.hpp>
+
+#include <memory>
+#include <string>
+#include <tuple>
+#include <vector>
+
+namespace phosphor::power::regulators
+{
+
+/**
+ * Define simple name for the generated C++ class that implements the
+ * xyz.openbmc_project.Sensor.Value interface.
+ */
+using ValueInterface = sdbusplus::xyz::openbmc_project::Sensor::server::Value;
+
+/**
+ * Define simple name for the generated C++ class that implements the
+ * xyz.openbmc_project.State.Decorator.OperationalStatus interface.
+ */
+using OperationalStatusInterface = sdbusplus::xyz::openbmc_project::State::
+ Decorator::server::OperationalStatus;
+
+/**
+ * Define simple name for the generated C++ class that implements the
+ * xyz.openbmc_project.State.Decorator.Availability interface.
+ */
+using AvailabilityInterface =
+ sdbusplus::xyz::openbmc_project::State::Decorator::server::Availability;
+
+/**
+ * Define simple name for the generated C++ class that implements the
+ * xyz.openbmc_project.Association.Definitions interface.
+ */
+using AssociationDefinitionsInterface =
+ sdbusplus::xyz::openbmc_project::Association::server::Definitions;
+
+/**
+ * Define simple name for the sdbusplus object_t class that implements all
+ * the necessary D-Bus interfaces via templates/multiple inheritance.
+ */
+using DBusSensorObject =
+ sdbusplus::server::object_t<ValueInterface, OperationalStatusInterface,
+ AvailabilityInterface,
+ AssociationDefinitionsInterface>;
+
+/**
+ * Define simple name for the generated C++ enum that implements the
+ * valid sensor Unit values on D-Bus.
+ */
+using Unit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit;
+
+/**
+ * Define simple name for the tuple used to create D-Bus associations.
+ */
+using AssocationTuple = std::tuple<std::string, std::string, std::string>;
+
+/**
+ * Root object path for sensors.
+ */
+constexpr const char* sensorsObjectPath = "/xyz/openbmc_project/sensors";
+
+/**
+ * @class DBusSensor
+ *
+ * This class represents a voltage regulator sensor on D-Bus.
+ *
+ * Each voltage rail in the system may provide multiple types of sensor data,
+ * such as temperature, output voltage, and output current. A DBusSensor tracks
+ * one of these data types for a voltage rail.
+ */
+class DBusSensor
+{
+ public:
+ // Specify which compiler-generated methods we want
+ DBusSensor() = delete;
+ DBusSensor(const DBusSensor&) = delete;
+ DBusSensor(DBusSensor&&) = delete;
+ DBusSensor& operator=(const DBusSensor&) = delete;
+ DBusSensor& operator=(DBusSensor&&) = delete;
+ virtual ~DBusSensor() = default;
+
+ /**
+ * Constructor.
+ *
+ * @param bus D-Bus bus object
+ * @param name sensor name
+ * @param type sensor type
+ * @param value sensor value
+ * @param rail voltage rail associated with this sensor
+ * @param deviceInventoryPath D-Bus inventory path of the voltage regulator
+ * device that produces the rail
+ * @param chassisInventoryPath D-Bus inventory path of the chassis that
+ * contains the voltage regulator device
+ */
+ explicit DBusSensor(sdbusplus::bus::bus& bus, const std::string& name,
+ SensorType type, double value, const std::string& rail,
+ const std::string& deviceInventoryPath,
+ const std::string& chassisInventoryPath);
+
+ /**
+ * Disable this sensor.
+ *
+ * Updates the sensor properties on D-Bus to indicate it is no longer
+ * receiving value updates.
+ *
+ * This method is normally called when the system is being powered off.
+ * Sensors are not read when the system is powered off.
+ */
+ void disable();
+
+ /**
+ * Return the sensor name.
+ *
+ * @return sensor name
+ */
+ const std::string& getName() const
+ {
+ return name;
+ }
+
+ /**
+ * Return the voltage regulator rail associated with this sensor.
+ *
+ * @return rail
+ */
+ const std::string& getRail() const
+ {
+ return rail;
+ }
+
+ /**
+ * Return the sensor type.
+ *
+ * @return sensor type
+ */
+ SensorType getType() const
+ {
+ return type;
+ }
+
+ /**
+ * Set this sensor to the error state.
+ *
+ * Updates the sensor properties on D-Bus to indicate an error occurred and
+ * the sensor value could not be read.
+ */
+ void setToErrorState();
+
+ /**
+ * Set the value of this sensor.
+ *
+ * Do not specify the value NaN. This special value is used internally to
+ * indicate the sensor has been disabled or is in the error state. Call the
+ * disable() or setToErrorState() method instead so that all affected D-Bus
+ * interfaces are updated correctly.
+ *
+ * @param value new sensor value
+ */
+ void setValue(double value);
+
+ private:
+ /**
+ * Sensor value update policy.
+ *
+ * Determines whether a new sensor value should replace the current value on
+ * D-Bus.
+ */
+ enum class ValueUpdatePolicy : unsigned char
+ {
+ /**
+ * Hysteresis value update policy.
+ *
+ * The sensor value will only be updated if the new value differs from
+ * the current value by at least the hysteresis amount. This avoids
+ * constant D-Bus traffic due to insignificant value changes.
+ */
+ hysteresis,
+
+ /**
+ * Highest value update policy.
+ *
+ * The sensor value will only be updated if the new value is higher than
+ * the current value.
+ *
+ * Some sensors contain the highest value observed by the voltage
+ * regulator, such as the highest temperature or highest output voltage.
+ * The regulator internally calculates this value since it can poll the
+ * value very quickly and can catch transient events.
+ *
+ * When the sensor is read from the regulator, the regulator will often
+ * clear its internal value. It will begin calculating a new highest
+ * value. For this reason, the D-Bus sensor value is set to the highest
+ * value that has been read across all monitoring cycles.
+ *
+ * The D-Bus sensor value is cleared when the sensor is disabled. This
+ * normally occurs when the system is powered off. Thus, the D-Bus
+ * sensor value is normally the highest value read since the system was
+ * powered on.
+ */
+ highest,
+
+ /**
+ * Lowest value update policy.
+ *
+ * The sensor value will only be updated if the new value is lower than
+ * the current value.
+ *
+ * Some sensors contain the lowest value observed by the voltage
+ * regulator, such as the lowest output current or lowest output
+ * voltage. The regulator internally calculates this value since it can
+ * poll the value very quickly and can catch transient events.
+ *
+ * When the sensor is read from the regulator, the regulator will often
+ * clear its internal value. It will begin calculating a new lowest
+ * value. For this reason, the D-Bus sensor value is set to the lowest
+ * value that has been read across all monitoring cycles.
+ *
+ * The D-Bus sensor value is cleared when the sensor is disabled. This
+ * normally occurs when the system is powered off. Thus, the D-Bus
+ * sensor value is normally the lowest value read since the system was
+ * powered on.
+ */
+ lowest
+ };
+
+ /**
+ * Get the D-Bus associations to create for this sensor.
+ *
+ * @param deviceInventoryPath D-Bus inventory path of the voltage regulator
+ * device that produces the rail
+ * @param chassisInventoryPath D-Bus inventory path of the chassis that
+ * contains the voltage regulator device
+ */
+ std::vector<AssocationTuple>
+ getAssociations(const std::string& deviceInventoryPath,
+ const std::string& chassisInventoryPath);
+
+ /**
+ * Get sensor properties that are based on the sensor type.
+ *
+ * The properties are returned in output parameters.
+ *
+ * Also initializes some data members whose value is based on the sensor
+ * type.
+ *
+ * @param objectPath returns the object path of this sensor
+ * @param unit returns the D-Bus unit for the sensor value
+ * @param minValue returns the minimum sensor value
+ * @param maxValue returns the maximum sensor value
+ */
+ void getTypeBasedProperties(std::string& objectPath, Unit& unit,
+ double& minValue, double& maxValue);
+
+ /**
+ * Set the sensor value on D-Bus to NaN.
+ */
+ void setValueToNaN();
+
+ /**
+ * Returns whether to update the sensor value on D-Bus with the specified
+ * new value.
+ *
+ * @param value new sensor value
+ * @return true if value should be updated on D-Bus, false otherwise
+ */
+ bool shouldUpdateValue(double value);
+
+ /**
+ * D-Bus bus object.
+ */
+ sdbusplus::bus::bus& bus;
+
+ /**
+ * Sensor name.
+ */
+ std::string name{};
+
+ /**
+ * Sensor type.
+ */
+ SensorType type;
+
+ /**
+ * Voltage regulator rail associated with this sensor.
+ */
+ std::string rail{};
+
+ /**
+ * Sensor value update policy.
+ */
+ ValueUpdatePolicy updatePolicy{ValueUpdatePolicy::hysteresis};
+
+ /**
+ * Hysteresis value.
+ *
+ * Only used when updatePolicy is hysteresis.
+ */
+ double hysteresis{0.0};
+
+ /**
+ * sdbusplus object_t class that implements all the necessary D-Bus
+ * interfaces via templates and multiple inheritance.
+ */
+ std::unique_ptr<DBusSensorObject> dbusObject{};
+};
+
+} // namespace phosphor::power::regulators