control: remove NaN from D-Bus properties

When sensors are offline, its possible for some driver parameters to
appear as NaN. These values are prevented from being stored in fan
control and are removed if they are detected in the cache.

Signed-off-by: Mike Capps <mikepcapps@gmail.com>
Change-Id: I22aa0c551faffdfc83eb1992b1242ac477d08180
diff --git a/control/json/manager.cpp b/control/json/manager.cpp
index 978fde4..5bfa07c 100644
--- a/control/json/manager.cpp
+++ b/control/json/manager.cpp
@@ -475,6 +475,21 @@
     return paths;
 }
 
+void Manager::insertFilteredObjects(ManagedObjects& ref)
+{
+    for (auto& [path, pathMap] : ref)
+    {
+        for (auto& [intf, intfMap] : pathMap)
+        {
+            // for each property on this path+interface
+            for (auto& [prop, value] : intfMap)
+            {
+                setProperty(path, intf, prop, value);
+            }
+        }
+    }
+}
+
 void Manager::addObjects(const std::string& path, const std::string& intf,
                          const std::string& prop)
 {
@@ -494,58 +509,22 @@
     {
         // No object manager interface provided by service?
         // Attempt to retrieve property directly
-        auto variant = util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
+        auto value = util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
             _bus, service, path, intf, prop);
-        _objects[path][intf][prop] = variant;
+
+        setProperty(path, intf, prop, value);
         return;
     }
 
     for (const auto& objMgrPath : objMgrPaths)
     {
         // Get all managed objects of service
+        // want to filter here...
         auto objects = util::SDBusPlus::getManagedObjects<PropertyVariantType>(
             _bus, service, objMgrPath);
 
-        // Add what's returned to the cache of objects
-        for (auto& object : objects)
-        {
-            auto itPath = _objects.find(object.first);
-            if (itPath != _objects.end())
-            {
-                // Path found in cache
-                for (auto& interface : itPath->second)
-                {
-                    auto itIntf = itPath->second.find(interface.first);
-                    if (itIntf != itPath->second.end())
-                    {
-                        // Interface found in cache
-                        for (auto& property : itIntf->second)
-                        {
-                            auto itProp = itIntf->second.find(property.first);
-                            if (itProp != itIntf->second.end())
-                            {
-                                // Property found, update value
-                                itProp->second = property.second;
-                            }
-                            else
-                            {
-                                itIntf->second.insert(property);
-                            }
-                        }
-                    }
-                    else
-                    {
-                        // Interface not found in cache
-                        itPath->second.insert(interface);
-                    }
-                }
-            }
-            else
-            {
-                // Path not found in cache
-                _objects.insert(object);
-            }
-        }
+        // insert all objects but remove any NaN values
+        insertFilteredObjects(objects);
     }
 }
 
@@ -572,6 +551,25 @@
     return std::nullopt;
 }
 
+void Manager::setProperty(const std::string& path, const std::string& intf,
+                          const std::string& prop, PropertyVariantType value)
+{
+    // filter NaNs out of the cache
+    if (PropertyContainsNan(value))
+    {
+        // dont use operator [] if paths dont exist
+        if (_objects.find(path) != _objects.end() &&
+            _objects[path].find(intf) != _objects[path].end())
+        {
+            _objects[path][intf].erase(prop);
+        }
+    }
+    else
+    {
+        _objects[path][intf][prop] = std::move(value);
+    }
+}
+
 void Manager::addTimer(const TimerType type,
                        const std::chrono::microseconds interval,
                        std::unique_ptr<TimerPkg> pkg)