monitor: Read fan state from dbus inventory upon starting

tach sensors previously defaulted to functional. Now they default to the
inventory state. For counter-based sensors, nonfunctional state forces
the count to exceed the threshold.

Fan's functional state now depends on the number of functional sensors.

test plan:
1) power-off chassis, stop phosphor-fan-monitor service
2) use busctl to make a fan's tach sensor nonfunctional
3) start fan-monitor
4) verify the fan's state == nonfunctional
5) poweron chassis, verify that fan-monitor updates _sensor_ to
   functional
6) fan should remain nonfunctional
7) set Fan to non-present, then to present again (simulate
   replacement)
8) observe the fans functional state is now true in inventory

Signed-off-by: Mike Capps <mikepcapps@gmail.com>
Change-Id: I0a109a1d85390c0201f8a54942efcd2fb21a2b65
diff --git a/monitor/tach_sensor.cpp b/monitor/tach_sensor.cpp
index f110722..cc35c97 100644
--- a/monitor/tach_sensor.cpp
+++ b/monitor/tach_sensor.cpp
@@ -82,8 +82,39 @@
     _timer(event, std::bind(&Fan::updateState, &fan, std::ref(*this))),
     _errorDelay(errorDelay), _countInterval(countInterval)
 {
-    // Start from a known state of functional
-    setFunctional(true);
+    // Query functional state from inventory
+    // TODO - phosphor-fan-presence/issues/25
+    auto service = util::SDBusPlus::getService(
+        _bus, util::INVENTORY_PATH + _invName, util::OPERATIONAL_STATUS_INTF);
+
+    try
+    {
+        if (!service.empty())
+        {
+            _functional = util::SDBusPlus::getProperty<bool>(
+                service, util::INVENTORY_PATH + _invName,
+                util::OPERATIONAL_STATUS_INTF, util::FUNCTIONAL_PROPERTY);
+        }
+        else
+        {
+            // default to functional when service not up. Error handling done
+            // later
+            _functional = true;
+            updateInventory(_functional);
+        }
+    }
+    catch (util::DBusError& e)
+    {
+        log<level::DEBUG>(e.what());
+        _functional = true;
+        updateInventory(_functional);
+    }
+
+    if (!_functional && MethodMode::count == _method)
+    {
+        // force continual nonfunctional state
+        _counter = _threshold;
+    }
 
     // Load in current Target and Input values when entering monitor mode
 #ifndef MONITOR_USE_JSON