monitor: Use only init mode when using JSON

Fan monitor is currently split into 2 modes - 'init' which is used
right after a power on, and 'monitor', which is used later after the
fans-ready target is started.  Normally, the 'init' mode just sets the
fans to functional and then exits, and the real monitoring work is done
in the 'monitor' mode.

In the future this application will need to be able to check for fan
problems as soon as it starts up after power on so that it can handle
shutting down due to missing fans.  To prepare for this, move all
functionality into the init mode, and just exit immediately when called
to run in the monitor mode.  Only do this when compiled to use the JSON
configuration, as this is new and I don't want to change how the
existing YAML setups work.

This also creates a new 'monitor_start_delay' entry in the JSON to say
how long to wait after startup before actually doing any sensor
monitoring, which then gives the same behavior as how the monitor mode
would delay by waiting for the fan control ready target, which itself is
started by fan control --init after a hardcoded delay.  This field is
optional to preserve backwards compatibility and defaults to 0s.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I623a233f50233e734f50cd9e80139c60467518d8
diff --git a/monitor/fan.cpp b/monitor/fan.cpp
index 3b12905..525a22b 100644
--- a/monitor/fan.cpp
+++ b/monitor/fan.cpp
@@ -16,6 +16,7 @@
 #include "fan.hpp"
 
 #include "sdbusplus.hpp"
+#include "system.hpp"
 #include "types.hpp"
 #include "utility.hpp"
 
@@ -33,14 +34,21 @@
 {
 
 using namespace phosphor::logging;
+using namespace sdbusplus::bus::match;
 
 Fan::Fan(Mode mode, sdbusplus::bus::bus& bus, const sdeventplus::Event& event,
-         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def) :
+         std::unique_ptr<trust::Manager>& trust, const FanDefinition& def,
+         System& system) :
     _bus(bus),
     _name(std::get<fanNameField>(def)),
     _deviation(std::get<fanDeviationField>(def)),
     _numSensorFailsForNonFunc(std::get<numSensorFailsForNonfuncField>(def)),
-    _trustManager(trust)
+    _trustManager(trust),
+#ifdef MONITOR_USE_JSON
+    _monitorDelay(std::get<monitorStartDelayField>(def)),
+    _monitorTimer(event, std::bind(std::mem_fn(&Fan::startMonitor), this)),
+#endif
+    _system(system)
 {
     // Start from a known state of functional
     updateInventory(true);
@@ -70,20 +78,39 @@
         }
     }
 
+#ifndef MONITOR_USE_JSON
     // Check current tach state when entering monitor mode
     if (mode != Mode::init)
     {
+        _monitorReady = true;
+
         // The TachSensors will now have already read the input
         // and target values, so check them.
         tachChanged();
     }
+#else
+    // If it used the JSON config, then it also will do all the work
+    // out of fan-monitor-init, after _monitorDelay.
+    _monitorTimer.restartOnce(std::chrono::seconds(_monitorDelay));
+
+#endif
+}
+
+void Fan::startMonitor()
+{
+    _monitorReady = true;
+
+    tachChanged();
 }
 
 void Fan::tachChanged()
 {
-    for (auto& s : _sensors)
+    if (_monitorReady)
     {
-        tachChanged(*s);
+        for (auto& s : _sensors)
+        {
+            tachChanged(*s);
+        }
     }
 }