Add Available interface

Some sensors become unavailable and this is expected,
this adds the available interface to be able to track
this, and allows an external app to set this in cases
where the sensor cannot distinguish that it is not
working.

Tested: Set the property on d-bus, saw the property and
reading change

Change-Id: Ib52ee668caeccc590b95ad2b1ea60470721d28ab
Signed-off-by: James Feist <james.feist@linux.intel.com>
diff --git a/include/sensor.hpp b/include/sensor.hpp
index 6bf0eba..21878f3 100644
--- a/include/sensor.hpp
+++ b/include/sensor.hpp
@@ -12,6 +12,8 @@
 constexpr size_t sensorFailedPollTimeMs = 5000;
 
 constexpr const char* sensorValueInterface = "xyz.openbmc_project.Sensor.Value";
+constexpr const char* availableInterfaceName =
+    "xyz.openbmc_project.State.Decorator.Availability";
 struct Sensor
 {
     Sensor(const std::string& name,
@@ -36,9 +38,11 @@
     std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceWarning;
     std::shared_ptr<sdbusplus::asio::dbus_interface> thresholdInterfaceCritical;
     std::shared_ptr<sdbusplus::asio::dbus_interface> association;
+    std::shared_ptr<sdbusplus::asio::dbus_interface> availableInterface;
     double value = std::numeric_limits<double>::quiet_NaN();
     bool overriddenState = false;
     bool internalSet = false;
+    bool available = true;
     double hysteresisTrigger;
     double hysteresisPublish;
 
@@ -155,12 +159,35 @@
         {
             std::cerr << "error initializing critical threshold interface\n";
         }
+
+        if (!availableInterface)
+        {
+            availableInterface =
+                std::make_shared<sdbusplus::asio::dbus_interface>(
+                    conn, sensorInterface->get_object_path(),
+                    availableInterfaceName);
+            availableInterface->register_property(
+                "Available", true, [this](const bool propIn, bool& old) {
+                    if (propIn == old)
+                    {
+                        return 1;
+                    }
+                    if (!propIn)
+                    {
+                        updateValue(std::numeric_limits<double>::quiet_NaN());
+                    }
+                    old = propIn;
+                    available = propIn;
+                    return 1;
+                });
+            availableInterface->initialize();
+        }
     }
 
     void updateValue(const double& newValue)
     {
         // Ignore if overriding is enabled
-        if (overriddenState)
+        if (overriddenState || !available)
         {
             return;
         }