monitor: Add up/down count fault detection

Create an up/down count fault determination algorithm that
could be used in place of the current timer based outOfRange()
function.
The up/down count is a different method for determining when
a fan is faulted by counting up each iteration a rotor is
out of spec and removing those counts when the rotor
returns within spec.

Tested:
    1. Remove a fan and run Mihawk, the counter add 1 when sensor
       is out of spec, and replaced the fan back before hit the
       threshold, the counter decrement back to 0.
    2. Remove a fan, counter add 1 and mark the removed fan as
       nonfunctional when counter reaches the threshold, and
       Replaced the fan back, counter will decrement back to 0
       and fan back to functional.

Change-Id: I632dd2c7553b007beb7ae6bb694a590d2cfc2a1c
Signed-off-by: Jolie Ku <jolie_ku@wistron.com>
Signed-off-by: Matthew Barth <msbarth@us.ibm.com>
diff --git a/monitor/fan.cpp b/monitor/fan.cpp
index 3f36dc7..abc9743 100644
--- a/monitor/fan.cpp
+++ b/monitor/fan.cpp
@@ -71,7 +71,8 @@
                 mode, bus, *this, std::get<sensorNameField>(s),
                 std::get<hasTargetField>(s), std::get<funcDelay>(def),
                 std::get<targetInterfaceField>(s), std::get<factorField>(s),
-                std::get<offsetField>(s), std::get<timeoutField>(def),
+                std::get<offsetField>(s), std::get<methodField>(def),
+                std::get<thresholdField>(s), std::get<timeoutField>(def),
                 std::get<nonfuncRotorErrDelayField>(def), event));
 
             _trustManager->registerSensor(_sensors.back());
@@ -167,20 +168,44 @@
     {
         if (sensor.functional())
         {
-            // Start nonfunctional timer if not already running
-            sensor.startTimer(TimerMode::nonfunc);
+            switch (sensor.getMethod())
+            {
+                case MethodMode::timebased:
+                    // Start nonfunctional timer if not already running
+                    sensor.startTimer(TimerMode::nonfunc);
+                    break;
+                case MethodMode::count:
+                    sensor.setCounter(true);
+                    if (sensor.getCounter() >= sensor.getThreshold())
+                    {
+                        updateState(sensor);
+                    }
+                    break;
+            }
         }
     }
     else
     {
-        if (sensor.functional())
+        switch (sensor.getMethod())
         {
-            sensor.stopTimer();
-        }
-        else
-        {
-            // Start functional timer if not already running
-            sensor.startTimer(TimerMode::func);
+            case MethodMode::timebased:
+                if (sensor.functional())
+                {
+                    sensor.stopTimer();
+                }
+                else
+                {
+                    // Start functional timer if not already running
+                    sensor.startTimer(TimerMode::func);
+                }
+                break;
+            case MethodMode::count:
+                sensor.setCounter(false);
+                if (!sensor.functional() && sensor.getCounter() == 0)
+                {
+                    updateState(sensor);
+                }
+                break;
         }
     }
 }
@@ -233,7 +258,7 @@
     return false;
 }
 
-void Fan::timerExpired(TachSensor& sensor)
+void Fan::updateState(TachSensor& sensor)
 {
     sensor.setFunctional(!sensor.functional());