Handle OCC poll changes for per chip power data

Handle OCC poll change for per chip memory and processor data.
and Provide the data to Redfish

Change-Id: I88725599ec70d61fb43c1699520ea17ccac91243
Signed-off-by: Sheldon Bailey <baileysh@us.ibm.com>
diff --git a/occ_manager.cpp b/occ_manager.cpp
index f89c530..0a00c2e 100644
--- a/occ_manager.cpp
+++ b/occ_manager.cpp
@@ -1290,6 +1290,114 @@
     return;
 }
 
+void Manager::readExtnSensors(const fs::path& path, uint32_t id)
+{
+    std::regex expr{"extn\\d+_label$"}; // Example: extn5_label
+    for (auto& file : fs::directory_iterator(path))
+    {
+        if (!std::regex_search(file.path().string(), expr))
+        {
+            continue;
+        }
+
+        // Read in Label value of the sensor from file.
+        std::string labelValue;
+        try
+        {
+            labelValue = readFile<std::string>(file.path());
+        }
+        catch (const std::system_error& e)
+        {
+            lg2::debug(
+                "readExtnSensors:label Failed reading {PATH}, errno = {ERROR}",
+                "PATH", file.path().string(), "ERROR", e.code().value());
+            continue;
+        }
+        const std::string& tempLabel = "label";
+        const std::string filePathString = file.path().string().substr(
+            0, file.path().string().length() - tempLabel.length());
+
+        std::string sensorPath = OCC_SENSORS_ROOT + std::string("/power/");
+
+        // Labels of EXTN sections from OCC interface Document
+        //     have different formats.
+        // 0x464d494e : FMIN            0x46444953 : FDIS
+        // 0x46424153 : FBAS            0x46555400 : FUT
+        // 0x464d4158 : FMAX            0x434c4950 : CLIP
+        // 0x4d4f4445 : MODE            0x574f4643 : WOFC
+        // 0x574f4649 : WOFI            0x5057524d : PWRM
+        // 0x50575250 : PWRP            0x45525248 : ERRH
+        // Label indicating byte 5 and 6 is the current (mem,proc) power in
+        //      Watts.
+        if ((labelValue == EXTN_LABEL_PWRM_MEMORY_POWER) ||
+            (labelValue == EXTN_LABEL_PWRP_PROCESSOR_POWER))
+        {
+            // Build the dbus String for this chiplet power asset.
+            if (labelValue == EXTN_LABEL_PWRP_PROCESSOR_POWER)
+            {
+                labelValue = "_power";
+            }
+            else // else EXTN_LABEL_PWRM_MEMORY_POWER
+            {
+                labelValue = "_mem_power";
+            }
+            sensorPath.append("chiplet" + std::to_string(id) + labelValue);
+
+            // Read in data value of the sensor from file.
+            // Read in as string due to different format of data in sensors.
+            std::string extnValue;
+            try
+            {
+                extnValue = readFile<std::string>(filePathString + inputSuffix);
+            }
+            catch (const std::system_error& e)
+            {
+                lg2::debug(
+                    "readExtnSensors:value Failed reading {PATH}, errno = {ERROR}",
+                    "PATH", filePathString + inputSuffix, "ERROR",
+                    e.code().value());
+                continue;
+            }
+
+            // For Power field, Convert last 4 bytes of hex string into number
+            //   value.
+            std::stringstream ssData;
+            ssData << std::hex << extnValue.substr(extnValue.length() - 4);
+            uint16_t MyHexNumber;
+            ssData >> MyHexNumber;
+
+            // Convert output/DC power to input/AC power in Watts (round up)
+            MyHexNumber =
+                std::round(((MyHexNumber / (PS_DERATING_FACTOR / 100.0))));
+
+            lg2::debug("OCC{ID}: FILE:{FILE} -- {ACWATTS} AC Watts", "ID", id,
+                       "FILE", filePathString + inputSuffix, "ACWATTS",
+                       MyHexNumber);
+
+            dbus::OccDBusSensors::getOccDBus().setUnit(
+                sensorPath, "xyz.openbmc_project.Sensor.Value.Unit.Watts");
+
+            dbus::OccDBusSensors::getOccDBus().setValue(sensorPath,
+                                                        MyHexNumber);
+
+            dbus::OccDBusSensors::getOccDBus().setOperationalStatus(
+                sensorPath, true);
+
+            if (existingSensors.find(sensorPath) == existingSensors.end())
+            {
+                dbus::OccDBusSensors::getOccDBus().setChassisAssociation(
+                    sensorPath, {"all_sensors"});
+            }
+
+        } // End Extended Power Sensors.
+        // else put in other label formats here to dbus.
+
+        existingSensors[sensorPath] = id;
+
+    } // End For loop on files for Extended Sensors.
+    return;
+}
+
 void Manager::setSensorValueToNaN(uint32_t id) const
 {
     for (const auto& [sensorPath, occId] : existingSensors)
@@ -1332,6 +1440,7 @@
     {
         // Read temperature sensors
         readTempSensors(sensorPath, id);
+        readExtnSensors(sensorPath, id);
 
         if (occ->isMasterOcc())
         {
diff --git a/occ_manager.hpp b/occ_manager.hpp
index fa44ed0..fa34bf4 100644
--- a/occ_manager.hpp
+++ b/occ_manager.hpp
@@ -58,6 +58,9 @@
 constexpr auto ALTITUDE_INTERFACE = "xyz.openbmc_project.Sensor.Value";
 constexpr auto ALTITUDE_PROP = "Value";
 
+constexpr auto EXTN_LABEL_PWRM_MEMORY_POWER = "5057524d";
+constexpr auto EXTN_LABEL_PWRP_PROCESSOR_POWER = "50575250";
+
 /** @class Manager
  *  @brief Builds and manages OCC objects
  */
@@ -421,6 +424,13 @@
     void readTempSensors(const fs::path& path, uint32_t id);
 
     /**
+     * @brief Trigger OCC driver to read the extended sensors.
+     * @param[in] path - path of the OCC sensors.
+     * @param[in] id - Id of the OCC.
+     * */
+    void readExtnSensors(const fs::path& path, uint32_t id);
+
+    /**
      * @brief Trigger OCC driver to read the power sensors.
      * @param[in] path - path of the OCC sensors.
      * @param[in] id - Id of the OCC.