platform-mc: sensor: Support none-telemetry base unit

As [1], The sensor D-Bus object path `/xyz/openbmc_project/sensors/` and
`xyz.openbmc_project.Sensor.Value` interface are only used for the
telemetry sensor types which are listed. The non-telemetry PLDM sensor
with the `baseUnit` type `count`, `corrected_errors`,
`uncorrected_errors` and `oemunit` are none-telemetry types and are not
belong to that list.
Those unit types are metric types which are count of somethings so the
metric D-Bus object path `/xyz/openbmc_project/metric/` and D-Bus
`xyz.openbmc_project.Metric.Value` should be used as [2]. Support
creating D-Bus object path and polling sensor values for the numeric
sensor/compact numeric sensor PDRs with the BaseUnit type is
none-telemetry.

[1] https://github.com/openbmc/phosphor-dbus-interfaces/blob/90cfce16584253a5f524c718ce5a6ae7c33f7b8c/yaml/xyz/openbmc_project/Sensor/Value.interface.yaml#L1
[2] https://github.com/openbmc/phosphor-dbus-interfaces/blob/master/yaml/xyz/openbmc_project/Sensor/Value.interface.yaml

Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Change-Id: Iaf8d842e6ec0cb082b139d15da1a1bd10a701acf
diff --git a/platform-mc/numeric_sensor.cpp b/platform-mc/numeric_sensor.cpp
index 6b387dd..2f56bbf 100644
--- a/platform-mc/numeric_sensor.cpp
+++ b/platform-mc/numeric_sensor.cpp
@@ -28,6 +28,8 @@
     sensorId = pdr->sensor_id;
     std::string path;
     SensorUnit sensorUnit = SensorUnit::DegreesC;
+    MetricUnit metricUnit = MetricUnit::Count;
+    useMetricInterface = false;
 
     switch (pdr->base_unit)
     {
@@ -59,6 +61,16 @@
             sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/";
             sensorUnit = SensorUnit::Percent;
             break;
+        case PLDM_SENSOR_UNIT_COUNTS:
+        case PLDM_SENSOR_UNIT_CORRECTED_ERRORS:
+        case PLDM_SENSOR_UNIT_UNCORRECTABLE_ERRORS:
+            sensorNameSpace = "/xyz/openbmc_project/metric/count/";
+            useMetricInterface = true;
+            break;
+        case PLDM_SENSOR_UNIT_OEMUNIT:
+            sensorNameSpace = "/xyz/openbmc_project/metric/oem/";
+            useMetricInterface = true;
+            break;
         default:
             lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME",
                        sensorName, "UNIT", pdr->base_unit);
@@ -70,9 +82,16 @@
     path = sensorNameSpace + sensorName;
     try
     {
-        auto service = pldm::utils::DBusHandler().getService(
-            path.c_str(), "xyz.openbmc_project.Sensor.Value");
-        if (!service.empty())
+        std::string tmp{};
+        std::string interface = SENSOR_VALUE_INTF;
+        if (useMetricInterface)
+        {
+            interface = METRIC_VALUE_INTF;
+        }
+        tmp = pldm::utils::DBusHandler().getService(path.c_str(),
+                                                    interface.c_str());
+
+        if (!tmp.empty())
         {
             throw sdbusplus::xyz::openbmc_project::Common::Error::
                 TooManyResources();
@@ -275,21 +294,44 @@
         updateTime = pdr->update_interval * 1000000;
     }
 
-    try
+    if (!useMetricInterface)
     {
-        valueIntf = std::make_unique<ValueIntf>(bus, path.c_str());
+        try
+        {
+            valueIntf = std::make_unique<ValueIntf>(bus, path.c_str());
+        }
+        catch (const sdbusplus::exception_t& e)
+        {
+            lg2::error(
+                "Failed to create Value interface for numeric sensor {PATH} error - {ERROR}",
+                "PATH", path, "ERROR", e);
+            throw sdbusplus::xyz::openbmc_project::Common::Error::
+                InvalidArgument();
+        }
+        valueIntf->maxValue(unitModifier(conversionFormula(maxValue)));
+        valueIntf->minValue(unitModifier(conversionFormula(minValue)));
+        valueIntf->unit(sensorUnit);
     }
-    catch (const sdbusplus::exception_t& e)
+    else
     {
-        lg2::error(
-            "Failed to create Value interface for numeric sensor {PATH} error - {ERROR}",
-            "PATH", path, "ERROR", e);
-        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
+        try
+        {
+            metricIntf = std::make_unique<MetricIntf>(bus, path.c_str());
+        }
+        catch (const sdbusplus::exception_t& e)
+        {
+            lg2::error(
+                "Failed to create Metric interface for numeric sensor {PATH} error - {ERROR}",
+                "PATH", path, "ERROR", e);
+            throw sdbusplus::xyz::openbmc_project::Common::Error::
+                InvalidArgument();
+        }
+        metricIntf->maxValue(unitModifier(conversionFormula(maxValue)));
+        metricIntf->minValue(unitModifier(conversionFormula(minValue)));
+        metricIntf->unit(metricUnit);
     }
-    valueIntf->maxValue(unitModifier(conversionFormula(maxValue)));
-    valueIntf->minValue(unitModifier(conversionFormula(minValue)));
+
     hysteresis = unitModifier(conversionFormula(hysteresis));
-    valueIntf->unit(sensorUnit);
 
     try
     {
@@ -319,7 +361,7 @@
     }
     operationalStatusIntf->functional(!sensorDisabled);
 
-    if (hasWarningThresholds)
+    if (hasWarningThresholds && !useMetricInterface)
     {
         try
         {
@@ -338,7 +380,7 @@
         thresholdWarningIntf->warningLow(unitModifier(warningLow));
     }
 
-    if (hasCriticalThresholds)
+    if (hasCriticalThresholds && !useMetricInterface)
     {
         try
         {
@@ -372,6 +414,8 @@
     sensorId = pdr->sensor_id;
     std::string path;
     SensorUnit sensorUnit = SensorUnit::DegreesC;
+    MetricUnit metricUnit = MetricUnit::Count;
+    useMetricInterface = false;
 
     switch (pdr->base_unit)
     {
@@ -403,6 +447,16 @@
             sensorNameSpace = "/xyz/openbmc_project/sensors/utilization/";
             sensorUnit = SensorUnit::Percent;
             break;
+        case PLDM_SENSOR_UNIT_COUNTS:
+        case PLDM_SENSOR_UNIT_CORRECTED_ERRORS:
+        case PLDM_SENSOR_UNIT_UNCORRECTABLE_ERRORS:
+            sensorNameSpace = "/xyz/openbmc_project/metric/count/";
+            useMetricInterface = true;
+            break;
+        case PLDM_SENSOR_UNIT_OEMUNIT:
+            sensorNameSpace = "/xyz/openbmc_project/metric/oem/";
+            useMetricInterface = true;
+            break;
         default:
             lg2::error("Sensor {NAME} has Invalid baseUnit {UNIT}.", "NAME",
                        sensorName, "UNIT", pdr->base_unit);
@@ -414,9 +468,16 @@
     path = sensorNameSpace + sensorName;
     try
     {
-        auto service = pldm::utils::DBusHandler().getService(
-            path.c_str(), "xyz.openbmc_project.Sensor.Value");
-        if (!service.empty())
+        std::string tmp{};
+        std::string interface = SENSOR_VALUE_INTF;
+        if (useMetricInterface)
+        {
+            interface = METRIC_VALUE_INTF;
+        }
+        tmp = pldm::utils::DBusHandler().getService(path.c_str(),
+                                                    interface.c_str());
+
+        if (!tmp.empty())
         {
             throw sdbusplus::xyz::openbmc_project::Common::Error::
                 TooManyResources();
@@ -485,21 +546,45 @@
      * updateTime is in microseconds
      */
     updateTime = static_cast<uint64_t>(DEFAULT_SENSOR_UPDATER_INTERVAL * 1000);
-    try
+
+    if (!useMetricInterface)
     {
-        valueIntf = std::make_unique<ValueIntf>(bus, path.c_str());
+        try
+        {
+            valueIntf = std::make_unique<ValueIntf>(bus, path.c_str());
+        }
+        catch (const sdbusplus::exception_t& e)
+        {
+            lg2::error(
+                "Failed to create Value interface for compact numeric sensor {PATH} error - {ERROR}",
+                "PATH", path, "ERROR", e);
+            throw sdbusplus::xyz::openbmc_project::Common::Error::
+                InvalidArgument();
+        }
+        valueIntf->maxValue(unitModifier(conversionFormula(maxValue)));
+        valueIntf->minValue(unitModifier(conversionFormula(minValue)));
+        valueIntf->unit(sensorUnit);
     }
-    catch (const sdbusplus::exception_t& e)
+    else
     {
-        lg2::error(
-            "Failed to create Value interface for compact numeric sensor {PATH} error - {ERROR}",
-            "PATH", path, "ERROR", e);
-        throw sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument();
+        try
+        {
+            metricIntf = std::make_unique<MetricIntf>(bus, path.c_str());
+        }
+        catch (const sdbusplus::exception_t& e)
+        {
+            lg2::error(
+                "Failed to create Metric interface for compact numeric sensor {PATH} error - {ERROR}",
+                "PATH", path, "ERROR", e);
+            throw sdbusplus::xyz::openbmc_project::Common::Error::
+                InvalidArgument();
+        }
+        metricIntf->maxValue(unitModifier(conversionFormula(maxValue)));
+        metricIntf->minValue(unitModifier(conversionFormula(minValue)));
+        metricIntf->unit(metricUnit);
     }
-    valueIntf->maxValue(unitModifier(conversionFormula(maxValue)));
-    valueIntf->minValue(unitModifier(conversionFormula(minValue)));
+
     hysteresis = unitModifier(conversionFormula(hysteresis));
-    valueIntf->unit(sensorUnit);
 
     try
     {
@@ -529,7 +614,7 @@
     }
     operationalStatusIntf->functional(!sensorDisabled);
 
-    if (hasWarningThresholds)
+    if (hasWarningThresholds && !useMetricInterface)
     {
         try
         {
@@ -548,7 +633,7 @@
         thresholdWarningIntf->warningLow(unitModifier(warningLow));
     }
 
-    if (hasCriticalThresholds)
+    if (hasCriticalThresholds && !useMetricInterface)
     {
         try
         {
@@ -583,7 +668,9 @@
 
 void NumericSensor::updateReading(bool available, bool functional, double value)
 {
-    if (!availabilityIntf || !operationalStatusIntf || !valueIntf)
+    if (!availabilityIntf || !operationalStatusIntf ||
+        (!useMetricInterface && !valueIntf) ||
+        (useMetricInterface && !metricIntf))
     {
         lg2::error(
             "Failed to update sensor {NAME} D-Bus interface don't exist.",
@@ -592,7 +679,16 @@
     }
     availabilityIntf->available(available);
     operationalStatusIntf->functional(functional);
-    double curValue = valueIntf->value();
+    double curValue = 0;
+    if (!useMetricInterface)
+    {
+        curValue = valueIntf->value();
+    }
+    else
+    {
+        curValue = metricIntf->value();
+    }
+
     double newValue = std::numeric_limits<double>::quiet_NaN();
     if (functional && available)
     {
@@ -600,8 +696,15 @@
         if (newValue != curValue &&
             (!std::isnan(newValue) || !std::isnan(curValue)))
         {
-            valueIntf->value(newValue);
-            updateThresholds();
+            if (!useMetricInterface)
+            {
+                valueIntf->value(newValue);
+                updateThresholds();
+            }
+            else
+            {
+                metricIntf->value(newValue);
+            }
         }
     }
     else
@@ -609,14 +712,22 @@
         if (newValue != curValue &&
             (!std::isnan(newValue) || !std::isnan(curValue)))
         {
-            valueIntf->value(std::numeric_limits<double>::quiet_NaN());
+            if (!useMetricInterface)
+            {
+                valueIntf->value(std::numeric_limits<double>::quiet_NaN());
+            }
+            else
+            {
+                metricIntf->value(std::numeric_limits<double>::quiet_NaN());
+            }
         }
     }
 }
 
 void NumericSensor::handleErrGetSensorReading()
 {
-    if (!operationalStatusIntf || !valueIntf)
+    if (!operationalStatusIntf || (!useMetricInterface && !valueIntf) ||
+        (useMetricInterface && !metricIntf))
     {
         lg2::error(
             "Failed to update sensor {NAME} D-Bus interfaces don't exist.",
@@ -624,7 +735,14 @@
         return;
     }
     operationalStatusIntf->functional(false);
-    valueIntf->value(std::numeric_limits<double>::quiet_NaN());
+    if (!useMetricInterface)
+    {
+        valueIntf->value(std::numeric_limits<double>::quiet_NaN());
+    }
+    else
+    {
+        metricIntf->value(std::numeric_limits<double>::quiet_NaN());
+    }
 }
 
 bool NumericSensor::checkThreshold(bool alarm, bool direction, double value,
@@ -657,16 +775,24 @@
 
 void NumericSensor::updateThresholds()
 {
-    if (!valueIntf)
+    double value = std::numeric_limits<double>::quiet_NaN();
+
+    if ((!useMetricInterface && !valueIntf) ||
+        (useMetricInterface && !metricIntf))
     {
         lg2::error(
             "Failed to update thresholds sensor {NAME} D-Bus interfaces don't exist.",
             "NAME", sensorName);
         return;
     }
-
-    auto value = valueIntf->value();
-
+    if (!useMetricInterface)
+    {
+        value = valueIntf->value();
+    }
+    else
+    {
+        value = metricIntf->value();
+    }
     if (thresholdWarningIntf &&
         !std::isnan(thresholdWarningIntf->warningHigh()))
     {
diff --git a/platform-mc/numeric_sensor.hpp b/platform-mc/numeric_sensor.hpp
index 92c709f..307f5e0 100644
--- a/platform-mc/numeric_sensor.hpp
+++ b/platform-mc/numeric_sensor.hpp
@@ -8,6 +8,7 @@
 
 #include <sdbusplus/server/object.hpp>
 #include <xyz/openbmc_project/Association/Definitions/server.hpp>
+#include <xyz/openbmc_project/Metric/Value/server.hpp>
 #include <xyz/openbmc_project/Sensor/Threshold/Critical/server.hpp>
 #include <xyz/openbmc_project/Sensor/Threshold/Warning/server.hpp>
 #include <xyz/openbmc_project/Sensor/Value/server.hpp>
@@ -21,9 +22,15 @@
 namespace platform_mc
 {
 
+constexpr const char* SENSOR_VALUE_INTF = "xyz.openbmc_project.Sensor.Value";
+constexpr const char* METRIC_VALUE_INTF = "xyz.openbmc_project.Metric.Value";
+
 using SensorUnit = sdbusplus::xyz::openbmc_project::Sensor::server::Value::Unit;
 using ValueIntf = sdbusplus::server::object_t<
     sdbusplus::xyz::openbmc_project::Sensor::server::Value>;
+using MetricUnit = sdbusplus::xyz::openbmc_project::Metric::server::Value::Unit;
+using MetricIntf = sdbusplus::server::object_t<
+    sdbusplus::xyz::openbmc_project::Metric::server::Value>;
 using ThresholdWarningIntf = sdbusplus::server::object_t<
     sdbusplus::xyz::openbmc_project::Sensor::Threshold::server::Warning>;
 using ThresholdCriticalIntf = sdbusplus::server::object_t<
@@ -206,6 +213,7 @@
      */
     void updateThresholds();
 
+    std::unique_ptr<MetricIntf> metricIntf = nullptr;
     std::unique_ptr<ValueIntf> valueIntf = nullptr;
     std::unique_ptr<ThresholdWarningIntf> thresholdWarningIntf = nullptr;
     std::unique_ptr<ThresholdCriticalIntf> thresholdCriticalIntf = nullptr;
@@ -226,6 +234,7 @@
 
     /** @brief A power-of-10 multiplier for baseUnit */
     int8_t baseUnitModifier;
+    bool useMetricInterface = false;
 };
 } // namespace platform_mc
 } // namespace pldm