Support any message type in /subscribe callbacks

Instead of hardcoding the possible variant types in
the PropertiesChanged and InterfacesAdded callbacks used
by the /subscribe REST operation, use convertDBusToJSON
which can convert every D-Bus type to JSON.

Tested: With the web UI running:
* Restart the State.Host service, which triggers an
  InterfacesAdded callback since the web UI subscribes
  to that.  It no longer crashes bmcweb with an sdbusplus
  error.
* Change power states, and verify the web UI sees them
  through its subscription on the CurrentHostState property.

Resolves openbmc/bmcweb#35

Change-Id: Ifa16c159d199005b42e3dfd4419bd3f9792c2d22
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/include/dbus_monitor.hpp b/include/dbus_monitor.hpp
index 44a7a94..d4f2647 100644
--- a/include/dbus_monitor.hpp
+++ b/include/dbus_monitor.hpp
@@ -5,6 +5,7 @@
 #include <boost/container/flat_map.hpp>
 #include <boost/container/flat_set.hpp>
 #include <dbus_singleton.hpp>
+#include <openbmc_dbus_rest.hpp>
 #include <sdbusplus/bus/match.hpp>
 #include <sdbusplus/message/types.hpp>
 
@@ -52,34 +53,50 @@
         return 0;
     }
     sdbusplus::message::message message(m);
-    using VariantType = sdbusplus::message::variant<std::string, bool, int64_t,
-                                                    uint64_t, double>;
     nlohmann::json j{{"event", message.get_member()},
                      {"path", message.get_path()}};
     if (strcmp(message.get_member(), "PropertiesChanged") == 0)
     {
-        std::string interface_name;
-        boost::container::flat_map<std::string, VariantType> values;
-        message.read(interface_name, values);
-        j["properties"] = values;
-        j["interface"] = std::move(interface_name);
+        nlohmann::json data;
+        int r = openbmc_mapper::convertDBusToJSON("sa{sv}as", message, data);
+        if (r < 0)
+        {
+            BMCWEB_LOG_ERROR << "convertDBusToJSON failed with " << r;
+            return 0;
+        }
+        if (!data.is_array())
+        {
+            BMCWEB_LOG_ERROR << "No data in PropertiesChanged signal";
+            return 0;
+        }
+
+        // data is type sa{sv}as and is an array[3] of string, object, array
+        j["interface"] = data[0];
+        j["properties"] = data[1];
     }
     else if (strcmp(message.get_member(), "InterfacesAdded") == 0)
     {
-        std::string object_name;
-        boost::container::flat_map<
-            std::string, boost::container::flat_map<std::string, VariantType>>
-            values;
-        message.read(object_name, values);
-        for (const std::pair<
-                 std::string,
-                 boost::container::flat_map<std::string, VariantType>>& paths :
-             values)
+        nlohmann::json data;
+        int r = openbmc_mapper::convertDBusToJSON("oa{sa{sv}}", message, data);
+        if (r < 0)
         {
-            auto it = thisSession->second.interfaces.find(paths.first);
+            BMCWEB_LOG_ERROR << "convertDBusToJSON failed with " << r;
+            return 0;
+        }
+
+        if (!data.is_array())
+        {
+            BMCWEB_LOG_ERROR << "No data in InterfacesAdded signal";
+            return 0;
+        }
+
+        // data is type oa{sa{sv}} which is an array[2] of string, object
+        for (auto& entry : data[1].items())
+        {
+            auto it = thisSession->second.interfaces.find(entry.key());
             if (it != thisSession->second.interfaces.end())
             {
-                j["interfaces"][paths.first] = paths.second;
+                j["interfaces"][entry.key()] = entry.value();
             }
         }
     }