[dbus-passive] Add threshold fan failure

When a threshold is crossed for a monitored sensor,
assert fan failure.

Tested-by: Changed a sensor threshold so that its current
reading made the threshold asserted and noticed via print
messages that the sensor went into failure state. Also
noticed fans ramp. Wrote unit test to verify sensor can
move in and out of error state correctly.

Change-Id: I83182536e4874eaba97f3f1d48d53ac110fba833
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/dbus/dbuspassive.cpp b/dbus/dbuspassive.cpp
index 702bf8d..a43b024 100644
--- a/dbus/dbuspassive.cpp
+++ b/dbus/dbuspassive.cpp
@@ -58,6 +58,7 @@
     _scale = settings.scale;
     _value = settings.value * pow(10, _scale);
     _updated = std::chrono::high_resolution_clock::now();
+    _failed = _helper->ThresholdsAsserted(tempBus, service, path);
 }
 
 ReadReturn DbusPassive::read(void)
@@ -77,6 +78,16 @@
     _updated = std::chrono::high_resolution_clock::now();
 }
 
+bool DbusPassive::getFailed(void) const
+{
+    return _failed;
+}
+
+void DbusPassive::setFailed(bool value)
+{
+    _failed = value;
+}
+
 int64_t DbusPassive::getScale(void)
 {
     return _scale;
@@ -90,7 +101,8 @@
 int HandleSensorValue(sdbusplus::message::message& msg, DbusPassive* owner)
 {
     std::string msgSensor;
-    std::map<std::string, sdbusplus::message::variant<int64_t, double>> msgData;
+    std::map<std::string, sdbusplus::message::variant<int64_t, double, bool>>
+        msgData;
 
     msg.read(msgSensor, msgData);
 
@@ -107,6 +119,32 @@
             owner->setValue(value);
         }
     }
+    else if (msgSensor == "xyz.openbmc_project.Sensor.Threshold.Critical")
+    {
+        auto criticalAlarmLow = msgData.find("CriticalAlarmLow");
+        auto criticalAlarmHigh = msgData.find("CriticalAlarmHigh");
+        if (criticalAlarmHigh == msgData.end() &&
+            criticalAlarmLow == msgData.end())
+        {
+            return 0;
+        }
+
+        bool asserted = false;
+        if (criticalAlarmLow != msgData.end())
+        {
+            asserted = sdbusplus::message::variant_ns::get<bool>(
+                criticalAlarmLow->second);
+        }
+
+        // checking both as in theory you could de-assert one threshold and
+        // assert the other at the same moment
+        if (!asserted && criticalAlarmHigh != msgData.end())
+        {
+            asserted = sdbusplus::message::variant_ns::get<bool>(
+                criticalAlarmHigh->second);
+        }
+        owner->setFailed(asserted);
+    }
 
     return 0;
 }