dbus-sdr: Add hybrid sensors stack option

Because the dynamic sensor stack doesn't support non-threshold sensors,
this patch gives way for retrieving non-threshold sensors by walking
through the sensor.yaml. However, this patch filters out any threshold
sensors written in the sensor yaml file because the current dbus-sdr
already supports them.

The sensor stack has both dynamic and static in this patch, so this new
feature is named hybrid sensor stack.

Tested: Try the SDR get command
0xF9:
  entityID: 0x21
  entityInstance: 0
  interfaces:
    xyz.openbmc_project.State.Watchdog:
      ExpireAction:
        Offsets:
          0x00:
            assert: xyz.openbmc_project.State.Watchdog.Action.None
            type: string
          0x01:
            assert: xyz.openbmc_project.State.Watchdog.Action.HardReset
            type: string
          0x02:
            assert: xyz.openbmc_project.State.Watchdog.Action.PowerOff
            type: string
          0x03:
            assert: xyz.openbmc_project.State.Watchdog.Action.PowerCycle
            type: string
  mutability: Mutability::Read
  path: /xyz/openbmc_project/watchdog/host0
  readingType: assertion
  sensorNamePattern: nameLeaf
  sensorReadingType: 0x6F
  sensorType: 0x23
  serviceInterface: org.freedesktop.DBus.Properties

$ ipmitool sdr get host0
Sensor ID              : host0 (0xcd)
 Entity ID             : 33.0 (System Management Software)
 Sensor Type (Discrete): Watchdog2 (0x23)
 Sensor Reading        : 0h
 Event Message Control : Per-threshold
 States Asserted       : Watchdog2
                         [Hard reset]
 Event Status          : Event Messages Disabled
 Assertion Events      : Watchdog2
                         [Hard reset]
 Event Enable          : Event Messages Disabled
 Assertions Enabled    : Watchdog2
                         [Timer expired]
                         [Hard reset]
                         [Power down]
                         [Power cycle]
 OEM                   : 0

Signed-off-by: Scron Chang <Scron.Chang@quantatw.com>
Change-Id: I1ac16f483f2f725077de9c15595195b848a224ab
diff --git a/dbus-sdr/sdrutils.cpp b/dbus-sdr/sdrutils.cpp
index 5ea88d8..7788050 100644
--- a/dbus-sdr/sdrutils.cpp
+++ b/dbus-sdr/sdrutils.cpp
@@ -16,6 +16,19 @@
 
 #include "dbus-sdr/sdrutils.hpp"
 
+#ifdef FEATURE_HYBRID_SENSORS
+
+#include <ipmid/utils.hpp>
+namespace ipmi
+{
+namespace sensor
+{
+extern const IdInfoMap sensors;
+} // namespace sensor
+} // namespace ipmi
+
+#endif
+
 namespace details
 {
 uint16_t getSensorSubtree(std::shared_ptr<SensorSubTree>& subtree)
@@ -88,6 +101,31 @@
     bool sensorRez =
         lbdUpdateSensorTree("/xyz/openbmc_project/sensors", sensorInterfaces);
 
+#ifdef FEATURE_HYBRID_SENSORS
+
+    if (!ipmi::sensor::sensors.empty())
+    {
+        for (const auto& sensor : ipmi::sensor::sensors)
+        {
+            // Threshold sensors should not be emplaced in here.
+            if (boost::starts_with(sensor.second.sensorPath,
+                                   "/xyz/openbmc_project/sensors/"))
+            {
+                continue;
+            }
+
+            // The bus service name is not listed in ipmi::sensor::Info. Give it
+            // an empty string. For those function using non-threshold sensors,
+            // the bus service name will be retrieved in an alternative way.
+            boost::container::flat_map<std::string, std::vector<std::string>>
+                connectionMap{
+                    {"", {sensor.second.propertyInterfaces.begin()->first}}};
+            sensorTreePtr->emplace(sensor.second.sensorPath, connectionMap);
+        }
+    }
+
+#endif
+
     // Error if searching for sensors failed.
     if (!sensorRez)
     {
@@ -167,6 +205,19 @@
     return true;
 }
 
+#ifdef FEATURE_HYBRID_SENSORS
+// Static sensors are listed in sensor-gen.cpp.
+ipmi::sensor::IdInfoMap::const_iterator
+    findStaticSensor(const std::string& path)
+{
+    return std::find_if(
+        ipmi::sensor::sensors.begin(), ipmi::sensor::sensors.end(),
+        [&path](const ipmi::sensor::IdInfoMap::value_type& findSensor) {
+            return findSensor.second.sensorPath == path;
+        });
+}
+#endif
+
 std::string getSensorTypeStringFromPath(const std::string& path)
 {
     // get sensor type string from path, path is defined as