psu-ng: Read and validate input voltage

Read the input voltage reported by pmbus for each PSU. Determine the
actual voltage based on predefined thresholds. Then validate the actual
voltage is supported for the PSU model.

Tested:
Verified in Rainier 2U that the 2 present PSUs had a pmbus
voltage value of 208000 mV, which is then translated to a 220V PSU, and
that value is validated against the supported configuration.
Verified the additional data strings by printing them with debug
statements:
Aug 05 18:50:15 p10bmc phosphor-psu-monitor[3615]: ACTUAL_VOLTAGE: 208.000000
Aug 05 18:50:15 p10bmc phosphor-psu-monitor[3615]: CALLOUT_INVENTORY_PATH:
/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0
Aug 05 18:50:15 p10bmc phosphor-psu-monitor[3615]: EXPECTED_VOLTAGE: 220

Change-Id: Ic8c3b567c8265e90bce420f98ac6f1e131ff713b
Signed-off-by: Adriana Kobylak <anoo@us.ibm.com>
diff --git a/phosphor-power-supply/psu_manager.cpp b/phosphor-power-supply/psu_manager.cpp
index 08b103d..704020e 100644
--- a/phosphor-power-supply/psu_manager.cpp
+++ b/phosphor-power-supply/psu_manager.cpp
@@ -495,7 +495,10 @@
                       [](const auto& psu) { return psu->isPresent(); });
 
     // Validate the supported configurations. A system may support more than one
-    // power supply model configuration.
+    // power supply model configuration. Since all configurations need to be
+    // checked, the additional data would contain only the information of the
+    // last configuration that did not match.
+    std::map<std::string, std::string> tmpAdditionalData;
     for (const auto& config : supportedConfigs)
     {
         if (config.first != model)
@@ -504,14 +507,54 @@
         }
         if (presentCount != config.second.powerSupplyCount)
         {
-            additionalData["EXPECTED_COUNT"] =
+            tmpAdditionalData.clear();
+            tmpAdditionalData["EXPECTED_COUNT"] =
                 std::to_string(config.second.powerSupplyCount);
-            additionalData["ACTUAL_COUNT"] = std::to_string(presentCount);
+            tmpAdditionalData["ACTUAL_COUNT"] = std::to_string(presentCount);
             continue;
         }
+
+        bool voltageValidated = true;
+        for (const auto& psu : psus)
+        {
+            if (!psu->isPresent())
+            {
+                // Only present PSUs report a valid input voltage
+                continue;
+            }
+
+            double actualInputVoltage;
+            int inputVoltage;
+            psu->getInputVoltage(actualInputVoltage, inputVoltage);
+
+            if (std::find(config.second.inputVoltage.begin(),
+                          config.second.inputVoltage.end(),
+                          inputVoltage) == config.second.inputVoltage.end())
+            {
+                tmpAdditionalData.clear();
+                tmpAdditionalData["ACTUAL_VOLTAGE"] =
+                    std::to_string(actualInputVoltage);
+                for (const auto& voltage : config.second.inputVoltage)
+                {
+                    tmpAdditionalData["EXPECTED_VOLTAGE"] +=
+                        std::to_string(voltage) + " ";
+                }
+                tmpAdditionalData["CALLOUT_INVENTORY_PATH"] =
+                    psu->getInventoryPath();
+
+                voltageValidated = false;
+                break;
+            }
+        }
+        if (!voltageValidated)
+        {
+            continue;
+        }
+
         return true;
     }
 
+    additionalData.insert(tmpAdditionalData.begin(), tmpAdditionalData.end());
     return false;
 }