Update to get PSU Asset information from parsing JSON file

The purpose is to support multiple PMBus device drivers, so need to
flexibly read the required PSU asset information attribute from the
configuration file (/usr/share/phosphor-power/psu.json)
and update D-BUS.

Tested: Update phosphor-power_git.bb and add the
psu.json. The psu-monitor process runs normally and can obtain the
asset information of PSU via D-BUS and REST command.

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I780172724a397384c9fe3870e2e847580d131e72
diff --git a/power-supply/example/psu_fru.json b/example/psu.json
similarity index 100%
rename from power-supply/example/psu_fru.json
rename to example/psu.json
diff --git a/meson.build b/meson.build
index a9e7fb4..9cc02ad 100644
--- a/meson.build
+++ b/meson.build
@@ -1,5 +1,5 @@
 project(
-    'witherspoon-pfault-analysis',
+    'phosphor-power',
     'cpp',
     default_options: [
         'warning_level=3',
@@ -28,6 +28,8 @@
     'INPUT_HISTORY_BUSNAME_ROOT', get_option('input-history-busname-root'))
 conf.set_quoted(
     'INPUT_HISTORY_SENSOR_ROOT', get_option('input-history-sensor-root'))
+conf.set_quoted(
+    'PSU_JSON_PATH', '/usr/share/phosphor-power/psu.json')
 conf.set10(
     'UCD90160_DEVICE_ACCESS', get_option('ucd90160-access'))
 
diff --git a/power-supply/power_supply.cpp b/power-supply/power_supply.cpp
index 487921d..0758d2a 100644
--- a/power-supply/power_supply.cpp
+++ b/power-supply/power_supply.cpp
@@ -13,6 +13,8 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include "config.h"
+
 #include "power_supply.hpp"
 
 #include "elog-errors.hpp"
@@ -23,7 +25,6 @@
 
 #include <functional>
 #include <org/open_power/Witherspoon/Fault/error.hpp>
-#include <phosphor-logging/elog.hpp>
 #include <phosphor-logging/log.hpp>
 #include <xyz/openbmc_project/Common/Device/error.hpp>
 #include <xyz/openbmc_project/Software/Version/server.hpp>
@@ -52,19 +53,11 @@
 constexpr auto MESSAGE_PROP = "Message";
 constexpr auto RESOLVED_PROP = "Resolved";
 constexpr auto PRESENT_PROP = "Present";
-constexpr auto SN_PROP = "SerialNumber";
-constexpr auto PN_PROP = "PartNumber";
-constexpr auto MODEL_PROP = "Model";
-constexpr auto VERSION_PROP = "Version";
 constexpr auto VERSION_PURPOSE_PROP = "Purpose";
 
 constexpr auto INVENTORY_OBJ_PATH = "/xyz/openbmc_project/inventory";
 constexpr auto POWER_OBJ_PATH = "/org/openbmc/control/power0";
 
-constexpr auto SERIAL_NUMBER = "serial_number";
-constexpr auto PART_NUMBER = "part_number";
-constexpr auto FW_VERSION = "fw_version";
-constexpr auto CCIN = "ccin";
 constexpr auto INPUT_HISTORY = "input_history";
 
 PowerSupply::PowerSupply(const std::string& name, size_t inst,
@@ -88,6 +81,8 @@
     powerOnInterval(t),
     powerOnTimer(e, std::bind([this]() { this->powerOn = true; }))
 {
+    getAccessType();
+
     using namespace sdbusplus::bus;
     using namespace witherspoon::pmbus;
     std::uint16_t statusWord = 0;
@@ -124,6 +119,41 @@
     updatePowerState();
 }
 
+void PowerSupply::getAccessType()
+{
+    using namespace witherspoon::pmbus;
+    using namespace witherspoon::power::util;
+    fruJson = loadJSONFromFile(PSU_JSON_PATH);
+    if (fruJson == nullptr)
+    {
+        log<level::ERR>("InternalFailure when parsing the JSON file");
+        return;
+    }
+
+    auto type = fruJson.at("inventoryPMBusAccessType");
+
+    if (type == "Hwmon")
+    {
+        inventoryPMBusAccessType = Type::Hwmon;
+    }
+    else if (type == "DeviceDebug")
+    {
+        inventoryPMBusAccessType = Type::DeviceDebug;
+    }
+    else if (type == "Debug")
+    {
+        inventoryPMBusAccessType = Type::Debug;
+    }
+    else if (type == "HwmonDeviceDebug")
+    {
+        inventoryPMBusAccessType = Type::HwmonDeviceDebug;
+    }
+    else
+    {
+        inventoryPMBusAccessType = Type::Base;
+    }
+}
+
 void PowerSupply::captureCmd(util::NamesValues& nv, const std::string& cmd,
                              witherspoon::pmbus::Type type)
 {
@@ -647,52 +677,6 @@
     using namespace witherspoon::pmbus;
     using namespace sdbusplus::message;
 
-    // If any of these accesses fail, the fields will just be
-    // blank in the inventory.  Leave logging ReadFailure errors
-    // to analyze() as it runs continuously and will most
-    // likely hit and threshold them first anyway.  The
-    // readString() function will do the tracing of the failing
-    // path so this code doesn't need to.
-    std::string pn;
-    std::string sn;
-    std::string ccin;
-    std::string version;
-
-    if (present)
-    {
-        try
-        {
-            sn = pmbusIntf.readString(SERIAL_NUMBER, Type::HwmonDeviceDebug);
-        }
-        catch (ReadFailure& e)
-        {
-        }
-
-        try
-        {
-            pn = pmbusIntf.readString(PART_NUMBER, Type::HwmonDeviceDebug);
-        }
-        catch (ReadFailure& e)
-        {
-        }
-
-        try
-        {
-            ccin = pmbusIntf.readString(CCIN, Type::HwmonDeviceDebug);
-        }
-        catch (ReadFailure& e)
-        {
-        }
-
-        try
-        {
-            version = pmbusIntf.readString(FW_VERSION, Type::HwmonDeviceDebug);
-        }
-        catch (ReadFailure& e)
-        {
-        }
-    }
-
     // Build the object map and send it to the inventory
     using Properties = std::map<std::string, variant<std::string>>;
     using Interfaces = std::map<std::string, Properties>;
@@ -702,12 +686,45 @@
     Interfaces interfaces;
     Object object;
 
-    assetProps.emplace(SN_PROP, sn);
-    assetProps.emplace(PN_PROP, pn);
-    assetProps.emplace(MODEL_PROP, ccin);
-    interfaces.emplace(ASSET_IFACE, std::move(assetProps));
+    // If any of these accesses fail, the fields will just be
+    // blank in the inventory.  Leave logging ReadFailure errors
+    // to analyze() as it runs continuously and will most
+    // likely hit and threshold them first anyway.  The
+    // readString() function will do the tracing of the failing
+    // path so this code doesn't need to.
+    for (const auto& fru : fruJson.at("fruConfigs"))
+    {
+        if (fru.at("interface") == ASSET_IFACE)
+        {
+            try
+            {
+                assetProps.emplace(
+                    fru.at("propertyName"),
+                    present ? pmbusIntf.readString(fru.at("fileName"),
+                                                   inventoryPMBusAccessType)
+                            : "");
+            }
+            catch (ReadFailure& e)
+            {
+            }
+        }
+        else if (fru.at("interface") == VERSION_IFACE)
+        {
+            try
+            {
+                versionProps.emplace(
+                    fru.at("propertyName"),
+                    present ? pmbusIntf.readString(fru.at("fileName"),
+                                                   inventoryPMBusAccessType)
+                            : "");
+            }
+            catch (const std::exception& e)
+            {
+            }
+        }
+    }
 
-    versionProps.emplace(VERSION_PROP, version);
+    interfaces.emplace(ASSET_IFACE, std::move(assetProps));
     interfaces.emplace(VERSION_IFACE, std::move(versionProps));
 
     // For Notify(), just send the relative path of the inventory
diff --git a/power-supply/power_supply.hpp b/power-supply/power_supply.hpp
index d997423..0968a78 100644
--- a/power-supply/power_supply.hpp
+++ b/power-supply/power_supply.hpp
@@ -6,6 +6,7 @@
 #include "pmbus.hpp"
 #include "record_manager.hpp"
 
+#include <nlohmann/json.hpp>
 #include <sdbusplus/bus/match.hpp>
 #include <sdeventplus/clock.hpp>
 #include <sdeventplus/event.hpp>
@@ -17,7 +18,6 @@
 {
 namespace psu
 {
-
 namespace sdbusRule = sdbusplus::bus::match::rules;
 
 constexpr auto FAULT_COUNT = 3;
@@ -263,6 +263,22 @@
     size_t syncGPIONumber = 0;
 
     /**
+     * @brief The type of the power supply inventory pmbus access.
+     */
+    witherspoon::pmbus::Type inventoryPMBusAccessType;
+
+    /**
+     * @brief The JSON from the parsed power supply FRU JSON File.
+     */
+    nlohmann::json fruJson;
+
+    /**
+     * @brief get the power supply access type from the JSON file.
+     *
+     */
+    void getAccessType();
+
+    /**
      * @brief Callback for inventory property changes
      *
      * Process change of Present property for power supply.
@@ -376,7 +392,8 @@
      * Properties added:
      * - Serial Number
      * - Part Number
-     * - CCIN (Customer Card Identification Number) - added as the Model
+     * - Manufacturer
+     * - Model
      * - Firmware version
      */
     void updateInventory();