psu: Add code to get pollInterval from JSON file

Add in a helper function to open JSON file and parse out the configuration
properties. Use the helper function to get the pollInterval in the constructor.

Signed-off-by: Brandon Wyman <bjwyman@gmail.com>
Change-Id: Ia8cf1c148a1685e2e09703c02e469a0bff034af5
diff --git a/phosphor-power-supply/README.md b/phosphor-power-supply/README.md
index 085d143..50724d3 100644
--- a/phosphor-power-supply/README.md
+++ b/phosphor-power-supply/README.md
@@ -2,3 +2,11 @@
 
 Design document: https://github.com/openbmc/docs/blob/master/designs/psu-monitoring.md
 
+# JSON Configuration File
+
+The JSON configuration file should contain:
+
+## pollInterval
+Required property that specifies the delay between updating the power supply 
+status, period in milliseconds.
+
diff --git a/phosphor-power-supply/configurations/witherspoon/psu_config.json b/phosphor-power-supply/configurations/witherspoon/psu_config.json
new file mode 100644
index 0000000..aecbd20
--- /dev/null
+++ b/phosphor-power-supply/configurations/witherspoon/psu_config.json
@@ -0,0 +1,3 @@
+{
+    "pollInterval" : 1000
+}
diff --git a/phosphor-power-supply/main.cpp b/phosphor-power-supply/main.cpp
index 2622c6a..03ff3db 100644
--- a/phosphor-power-supply/main.cpp
+++ b/phosphor-power-supply/main.cpp
@@ -22,7 +22,7 @@
 
 #include <filesystem>
 
-using namespace phosphor::power::manager;
+using namespace phosphor::power;
 
 int main(int argc, char* argv[])
 {
@@ -57,9 +57,7 @@
         // handle both sd_events (for the timers) and dbus signals.
         bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL);
 
-        // TODO: Should get polling interval from JSON file.
-        auto pollInterval = std::chrono::milliseconds(1000);
-        PSUManager manager(bus, event, pollInterval);
+        manager::PSUManager manager(bus, event, configfile);
 
         return manager.run();
     }
diff --git a/phosphor-power-supply/psu_manager.hpp b/phosphor-power-supply/psu_manager.hpp
index 1052705..b3877b7 100644
--- a/phosphor-power-supply/psu_manager.hpp
+++ b/phosphor-power-supply/psu_manager.hpp
@@ -19,6 +19,11 @@
 namespace manager
 {
 
+struct json_properties
+{
+    int pollInterval;
+};
+
 /**
  * @class PSUManager
  *
@@ -40,13 +45,21 @@
      *
      * @param[in] bus - D-Bus bus object
      * @param[in] e - event object
-     * @param[in] i - polling interval in milliseconds
+     * @param[in] configfile - string path to the configuration file
      */
     PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
-               std::chrono::milliseconds i) :
-        bus(bus),
-        timer(e, std::bind(&PSUManager::analyze, this), i)
+               const std::string& configfile) :
+        bus(bus)
     {
+        // Parse out the JSON properties
+        json_properties properties = {0};
+        getJSONProperties(configfile, properties);
+
+        using namespace sdeventplus;
+        auto pollInterval = std::chrono::milliseconds(properties.pollInterval);
+        timer = std::make_unique<utility::Timer<ClockId::Monotonic>>(
+            e, std::bind(&PSUManager::analyze, this), pollInterval);
+
         // Subscribe to power state changes
         powerService = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);
         powerOnMatch = std::make_unique<sdbusplus::bus::match_t>(
@@ -58,6 +71,23 @@
         initialize();
     }
 
+    void getJSONProperties(const std::string& path, json_properties& p)
+    {
+        nlohmann::json configFileJSON = util::loadJSONFromFile(path.c_str());
+
+        if (configFileJSON == nullptr)
+        {
+            throw std::runtime_error("Failed to load JSON configuration file");
+        }
+
+        if (!configFileJSON.contains("pollInterval"))
+        {
+            throw std::runtime_error("Missing required pollInterval property");
+        }
+
+        p.pollInterval = configFileJSON.at("pollInterval");
+    }
+
     /**
      * Initializes the manager.
      *
@@ -98,7 +128,7 @@
      */
     int run()
     {
-        return timer.get_event().loop();
+        return timer->get_event().loop();
     }
 
     /**
@@ -124,7 +154,9 @@
     /**
      * The timer that runs to periodically check the power supplies.
      */
-    sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic> timer;
+    std::unique_ptr<
+        sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
+        timer;
 
     /**
      * Analyze the status of each of the power supplies.