sensor: Always add status interface, track fault file with class member

Always add the status interface regardless of whether there is a
fault file or not and update the functional property accordingly.

Added a new sensor class member to track the presence of fault file.

Resolves: openbmc/phosphor-hwmon#10
Signed-off-by: Brandon Kim <brandonkim@google.com>
Change-Id: I4480541691ccfa853d85151965428c564db8ba52
diff --git a/sensor.cpp b/sensor.cpp
index a9e4454..a88410b 100644
--- a/sensor.cpp
+++ b/sensor.cpp
@@ -8,6 +8,7 @@
 #include "sensorset.hpp"
 #include "sysfs.hpp"
 
+#include <cassert>
 #include <cmath>
 #include <cstring>
 #include <filesystem>
@@ -39,7 +40,7 @@
                const hwmonio::HwmonIOInterface* ioAccess,
                const std::string& devPath) :
     _sensor(sensor),
-    _ioAccess(ioAccess), _devPath(devPath), _scale(0)
+    _ioAccess(ioAccess), _devPath(devPath), _scale(0), _hasFaultFile(false)
 {
     auto chip = env::getEnv("GPIOCHIP", sensor);
     auto access = env::getEnv("GPIO", sensor);
@@ -135,16 +136,15 @@
     auto& objPath = std::get<std::string>(info);
 
     SensorValueType val = 0;
-    std::shared_ptr<StatusObject> statusIface = nullptr;
-    auto it = obj.find(InterfaceType::STATUS);
-    if (it != obj.end())
-    {
-        statusIface = std::any_cast<std::shared_ptr<StatusObject>>(it->second);
-    }
 
-    // If there's no fault file or the sensor has a fault file and
-    // its status is functional, read the input value.
-    if (!statusIface || statusIface->functional())
+    auto& statusIface = std::any_cast<std::shared_ptr<StatusObject>&>(
+        obj[InterfaceType::STATUS]);
+    // As long as addStatus is called before addValue, statusIface
+    // should never be nullptr
+    assert(statusIface);
+
+    // Only read the input value if the status is functional
+    if (statusIface->functional())
     {
         // RAII object for GPIO unlock / lock
         GpioLock gpioLock(getGpio());
@@ -200,11 +200,12 @@
     std::string faultID = _sensor.second;
     std::string entry = hwmon::entry::fault;
 
+    bool functional = true;
     auto sysfsFullPath =
         sysfs::make_sysfs_path(_ioAccess->path(), faultName, faultID, entry);
     if (fs::exists(sysfsFullPath))
     {
-        bool functional = true;
+        _hasFaultFile = true;
         try
         {
             uint32_t fault = _ioAccess->read(faultName, faultID, entry,
@@ -228,18 +229,17 @@
                 "Logging failing sysfs file",
                 phosphor::logging::entry("FILE=%s", sysfsFullPath.c_str()));
         }
-
-        static constexpr bool deferSignals = true;
-        auto& bus = *std::get<sdbusplus::bus::bus*>(info);
-
-        iface =
-            std::make_shared<StatusObject>(bus, objPath.c_str(), deferSignals);
-        // Set functional property
-        iface->functional(functional);
-
-        obj[InterfaceType::STATUS] = iface;
     }
 
+    static constexpr bool deferSignals = true;
+    auto& bus = *std::get<sdbusplus::bus::bus*>(info);
+
+    iface = std::make_shared<StatusObject>(bus, objPath.c_str(), deferSignals);
+    // Set functional property
+    iface->functional(functional);
+
+    obj[InterfaceType::STATUS] = iface;
+
     return iface;
 }