Add support for sensor override value

Write support Value property under xyz.openbmc_project.Sensor.Value
interface is added which will be used to do sensor override.
Sensor can be overridden by setting a value, which will be preserved,
till the service is restarted or Value is overridden again with NaN.

Change-Id: Ia606031a97e532cd12d768e36f1feaa4c7350620
Signed-off-by: Richard Marian Thomaiyar <richard.marian.thomaiyar@linux.intel.com>
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/sensors/include/sensor.hpp b/sensors/include/sensor.hpp
index dc9cdbe..62eec62 100644
--- a/sensors/include/sensor.hpp
+++ b/sensors/include/sensor.hpp
@@ -20,4 +20,17 @@
     std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceWarning;
     std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceCritical;
     double value = std::numeric_limits<double>::quiet_NaN();
+    double overriddenValue = std::numeric_limits<double>::quiet_NaN();
+    bool internalSet = false;
+    int setSensorValue(const double& newValue, double& oldValue)
+    {
+        if (internalSet)
+        {
+            internalSet = false;
+            oldValue = newValue;
+            return 1;
+        }
+        overriddenValue = newValue;
+        return 1;
+    }
 };
\ No newline at end of file
diff --git a/sensors/src/ADCSensor.cpp b/sensors/src/ADCSensor.cpp
index 09c62cf..4ce6dda 100644
--- a/sensors/src/ADCSensor.cpp
+++ b/sensors/src/ADCSensor.cpp
@@ -101,9 +101,11 @@
         try
         {
             float nvalue = std::stof(response);
-
             nvalue = (nvalue / sensorScaleFactor) / scaleFactor;
-
+            if (!isnan(overriddenValue))
+            {
+                nvalue = overriddenValue;
+            }
             if (nvalue != value)
             {
                 updateValue(nvalue);
@@ -157,7 +159,10 @@
 
 void ADCSensor::updateValue(const double &newValue)
 {
+    // Indicate that it is internal set call
+    internalSet = true;
     bool ret = sensorInterface->set_property("Value", newValue);
+    internalSet = false;
     value = newValue;
     checkThresholds();
 }
@@ -168,7 +173,10 @@
     // todo, get max and min from configuration
     sensorInterface->register_property("MaxValue", maxValue);
     sensorInterface->register_property("MinValue", minValue);
-    sensorInterface->register_property("Value", value);
+    sensorInterface->register_property(
+        "Value", value, [&](const double &newValue, double &oldValue) {
+            return setSensorValue(newValue, oldValue);
+        });
 
     for (auto &threshold : thresholds)
     {
diff --git a/sensors/src/CPUSensor.cpp b/sensors/src/CPUSensor.cpp
index eda9a3b..24e30c8 100644
--- a/sensors/src/CPUSensor.cpp
+++ b/sensors/src/CPUSensor.cpp
@@ -99,6 +99,10 @@
             float nvalue = std::stof(response);
             responseStream.clear();
             nvalue /= CPUSensor::sensorScaleFactor;
+            if (!isnan(overriddenValue))
+            {
+                nvalue = overriddenValue;
+            }
             if (nvalue != value)
             {
                 updateValue(nvalue);
@@ -162,7 +166,10 @@
 
 void CPUSensor::updateValue(const double &newValue)
 {
+    // Indicate that it is internal set call
+    internalSet = true;
     sensorInterface->set_property("Value", newValue);
+    internalSet = false;
     value = newValue;
     checkThresholds();
 }
@@ -173,7 +180,10 @@
     // todo, get max and min from configuration
     sensorInterface->register_property("MaxValue", maxValue);
     sensorInterface->register_property("MinValue", minValue);
-    sensorInterface->register_property("Value", value);
+    sensorInterface->register_property(
+        "Value", value, [&](const double &newValue, double &oldValue) {
+            return setSensorValue(newValue, oldValue);
+        });
 
     for (auto &threshold : thresholds)
     {
diff --git a/sensors/src/HwmonTempSensor.cpp b/sensors/src/HwmonTempSensor.cpp
index 8510563..48e3fa6 100644
--- a/sensors/src/HwmonTempSensor.cpp
+++ b/sensors/src/HwmonTempSensor.cpp
@@ -97,8 +97,11 @@
         try
         {
             float nvalue = std::stof(response);
-
             nvalue /= sensorScaleFactor;
+            if (!isnan(overriddenValue))
+            {
+                nvalue = overriddenValue;
+            }
             if (nvalue != value)
             {
                 updateValue(nvalue);
@@ -135,7 +138,6 @@
     }
     inputDev.assign(fd);
     waitTimer.expires_from_now(boost::posix_time::milliseconds(sensorPollMs));
-    ;
     waitTimer.async_wait([&](const boost::system::error_code &ec) {
         if (ec == boost::asio::error::operation_aborted)
         {
@@ -152,7 +154,10 @@
 
 void HwmonTempSensor::updateValue(const double &newValue)
 {
+    // Indicate that it is internal set call
+    internalSet = true;
     sensorInterface->set_property("Value", newValue);
+    internalSet = false;
     value = newValue;
     checkThresholds();
 }
@@ -163,7 +168,10 @@
     // todo, get max and min from configuration
     sensorInterface->register_property("MaxValue", maxValue);
     sensorInterface->register_property("MinValue", minValue);
-    sensorInterface->register_property("Value", value);
+    sensorInterface->register_property(
+        "Value", value, [&](const double &newValue, double &oldValue) {
+            return setSensorValue(newValue, oldValue);
+        });
 
     for (auto &threshold : thresholds)
     {
diff --git a/sensors/src/TachSensor.cpp b/sensors/src/TachSensor.cpp
index 0f441cd..a68c894 100644
--- a/sensors/src/TachSensor.cpp
+++ b/sensors/src/TachSensor.cpp
@@ -115,6 +115,10 @@
                 std::getline(responseStream, response);
                 float nvalue = std::stof(response);
                 responseStream.clear();
+                if (!isnan(overriddenValue))
+                {
+                    nvalue = overriddenValue;
+                }
                 if (nvalue != value)
                 {
                     updateValue(nvalue);
@@ -181,7 +185,10 @@
 
 void TachSensor::updateValue(const double &newValue)
 {
+    // Indicate that it is internal set call
+    internalSet = true;
     sensorInterface->set_property("Value", newValue);
+    internalSet = false;
     value = newValue;
     checkThresholds();
 }
@@ -192,7 +199,10 @@
     // todo, get max and min from configuration
     sensorInterface->register_property("MaxValue", maxValue);
     sensorInterface->register_property("MinValue", minValue);
-    sensorInterface->register_property("Value", value);
+    sensorInterface->register_property(
+        "Value", value, [&](const double &newValue, double &oldValue) {
+            return setSensorValue(newValue, oldValue);
+        });
 
     for (auto &threshold : thresholds)
     {