ExitAirSensor: Get power readings from PSU

Now that PSU Sensors work, remove todo. Also fix
a bug where a int32 should have been a double as the
value from d-bus is a double.

Tested: Ipmitool sensor list

Change-Id: Ic7b31c1091b8178dc23ca79fdc189b973095a8e3
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/include/ExitAirTempSensor.hpp b/include/ExitAirTempSensor.hpp
index 1e774cf..70c3f68 100644
--- a/include/ExitAirTempSensor.hpp
+++ b/include/ExitAirTempSensor.hpp
@@ -10,9 +10,9 @@
 struct CFMSensor : public Sensor
 {
     std::vector<std::string> tachs;
-    int32_t c1;
-    int32_t c2;
-    int32_t maxCFM;
+    double c1;
+    double c2;
+    double maxCFM;
     double tachMinPercent;
     double tachMaxPercent;
 
diff --git a/include/Utils.hpp b/include/Utils.hpp
index 7f24e21..d65fb83 100644
--- a/include/Utils.hpp
+++ b/include/Utils.hpp
@@ -26,6 +26,9 @@
 using SensorData = boost::container::flat_map<
     std::string, boost::container::flat_map<std::string, BasicVariantType>>;
 
+using GetSubTreeType = std::vector<
+    std::pair<std::string,
+              std::vector<std::pair<std::string, std::vector<std::string>>>>>;
 using SensorBaseConfiguration =
     std::pair<std::string,
               boost::container::flat_map<std::string, BasicVariantType>>;
@@ -57,6 +60,20 @@
     always
 };
 
+namespace mapper
+{
+constexpr const char* busName = "xyz.openbmc_project.ObjectMapper";
+constexpr const char* path = "/xyz/openbmc_project/object_mapper";
+constexpr const char* interface = "xyz.openbmc_project.ObjectMapper";
+constexpr const char* subtree = "GetSubTree";
+} // namespace mapper
+
+namespace properties
+{
+constexpr const char* interface = "org.freedesktop.DBus.Properties";
+constexpr const char* get = "Get";
+} // namespace properties
+
 template <typename T>
 inline T loadVariant(
     const boost::container::flat_map<std::string, BasicVariantType>& data,
diff --git a/include/sensor.hpp b/include/sensor.hpp
index 2a414da..3d81f1f 100644
--- a/include/sensor.hpp
+++ b/include/sensor.hpp
@@ -4,6 +4,8 @@
 #include <sdbusplus/asio/object_server.hpp>
 
 constexpr size_t sensorFailedPollTimeMs = 5000;
+
+constexpr const char* sensorValueInterface = "xyz.openbmc_project.Sensor.Value";
 struct Sensor
 {
     Sensor(const std::string& name, const std::string& path,
diff --git a/src/ExitAirTempSensor.cpp b/src/ExitAirTempSensor.cpp
index 5e9fc29..0736a55 100644
--- a/src/ExitAirTempSensor.cpp
+++ b/src/ExitAirTempSensor.cpp
@@ -141,10 +141,8 @@
                     pidConfigurationType, "Class");
             }
         },
-        "xyz.openbmc_project.ObjectMapper",
-        "/xyz/openbmc_project/object_mapper",
-        "xyz.openbmc_project.ObjectMapper", "GetSubTree", "/", 0,
-        std::array<std::string, 1>{pidConfigurationType});
+        mapper::busName, mapper::path, mapper::interface, mapper::subtree, "/",
+        0, std::array<std::string, 1>{pidConfigurationType});
 }
 
 CFMSensor::CFMSensor(std::shared_ptr<sdbusplus::asio::connection>& conn,
@@ -177,8 +175,7 @@
     }
 
     association = objectServer.add_interface(
-        "/xyz/openbmc_project/sensors/voltage/" + name,
-        "org.openbmc.Associations");
+        "/xyz/openbmc_project/sensors/cfm/" + name, "org.openbmc.Associations");
 
     setInitialProperties(conn);
     setupSensorMatch(
@@ -390,7 +387,7 @@
             });
         if (findReading == tachReadings.end())
         {
-            if (DEBUG)
+            if constexpr (DEBUG)
             {
                 std::cerr << "Can't find " << tachName << "in readings\n";
             }
@@ -447,10 +444,22 @@
         // Now calculate the CFM for this tach
         // CFMi = Ci * Qmaxi * TACHi
         totalCFM += ci * maxCFM * rpm;
+        if constexpr (DEBUG)
+        {
+            std::cerr << "totalCFM = " << totalCFM << "\n";
+            std::cerr << "Ci " << ci << " MaxCFM " << maxCFM << " rpm " << rpm
+                      << "\n";
+            std::cerr << "c1 " << c1 << " c2 " << c2 << " max "
+                      << tachMaxPercent << " min " << tachMinPercent << "\n";
+        }
     }
 
     // divide by 100 since rpm is in percent
     value = totalCFM / 100;
+    if constexpr (DEBUG)
+    {
+        std::cerr << "cfm value = " << value << "\n";
+    }
     return true;
 }
 
@@ -501,7 +510,6 @@
 
 void ExitAirTempSensor::setupMatches(void)
 {
-
     constexpr const std::array<const char*, 2> matchTypes = {
         "power", inletTemperatureSensor};
 
@@ -512,7 +520,12 @@
                                       sdbusplus::message::message& message) {
                              if (type == "power")
                              {
-                                 powerReadings[message.get_path()] = value;
+                                 std::string path = message.get_path();
+                                 if (path.find("PS") != std::string::npos &&
+                                     boost::ends_with(path, "Input_Power"))
+                                 {
+                                     powerReadings[message.get_path()] = value;
+                                 }
                              }
                              else if (type == inletTemperatureSensor)
                              {
@@ -534,8 +547,53 @@
         },
         "xyz.openbmc_project.HwmonTempSensor",
         std::string("/xyz/openbmc_project/sensors/") + inletTemperatureSensor,
-        "org.freedesktop.DBus.Properties", "Get",
-        "xyz.openbmc_project.Sensor.Value", "Value");
+        properties::interface, properties::get, sensorValueInterface, "Value");
+    dbusConnection->async_method_call(
+        [this](boost::system::error_code ec, const GetSubTreeType& subtree) {
+            if (ec)
+            {
+                std::cerr << "Error contacting mapper\n";
+                return;
+            }
+            for (const auto& item : subtree)
+            {
+                size_t lastSlash = item.first.rfind("/");
+                if (lastSlash == std::string::npos ||
+                    lastSlash == item.first.size() || !item.second.size())
+                {
+                    continue;
+                }
+                std::string sensorName = item.first.substr(lastSlash + 1);
+                if (boost::starts_with(sensorName, "PS") &&
+                    boost::ends_with(sensorName, "Input_Power"))
+                {
+                    const std::string& path = item.first;
+                    dbusConnection->async_method_call(
+                        [this, path](boost::system::error_code ec,
+                                     const std::variant<double>& value) {
+                            if (ec)
+                            {
+                                std::cerr << "Error getting value from " << path
+                                          << "\n";
+                            }
+
+                            double reading =
+                                std::visit(VariantToDoubleVisitor(), value);
+                            if constexpr (DEBUG)
+                            {
+                                std::cerr << path << "Reading " << reading
+                                          << "\n";
+                            }
+                            powerReadings[path] = reading;
+                        },
+                        item.second[0].first, item.first, properties::interface,
+                        properties::get, sensorValueInterface, "Value");
+                }
+            }
+        },
+        mapper::busName, mapper::path, mapper::interface, mapper::subtree,
+        "/xyz/openbmc_project/sensors/power", 0,
+        std::array<const char*, 1>{sensorValueInterface});
 }
 
 void ExitAirTempSensor::updateReading(void)
@@ -813,11 +871,6 @@
             if (exitAirSensor)
             {
                 exitAirSensor->cfmSensors = std::move(cfmSensors);
-
-                // todo: when power sensors are done delete this fake
-                // reading
-                exitAirSensor->powerReadings["foo"] = 144.0;
-
                 exitAirSensor->updateReading();
             }
         },