incremental
diff --git a/src/webserver_main.cpp b/src/webserver_main.cpp
index 2ec7e37..82b83a7 100644
--- a/src/webserver_main.cpp
+++ b/src/webserver_main.cpp
@@ -31,11 +31,196 @@
 #include <boost/asio.hpp>
 #include <boost/endian/arithmetic.hpp>
 
+#include <dbus/dbus.h>
+#include <boost/iostreams/stream.hpp>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+
 #include <iostream>
 #include <memory>
 #include <string>
 #include <unordered_set>
 
+using sensor_values = std::vector<std::pair<std::string, int32_t>>;
+
+std::vector<std::string> read_dbus_xml_names(std::string& xml_data) {
+  std::vector<std::string> values;
+  // populate tree structure pt
+  using boost::property_tree::ptree;
+  ptree pt;
+  boost::iostreams::stream<boost::iostreams::array_source> stream(
+      xml_data.c_str(), xml_data.size());
+  read_xml(stream, pt);
+
+  // traverse node to find other nodes
+  for (const auto& interface : pt.get_child("node")) {
+    if (interface.first == "node") {
+      auto t = interface.second.get<std::string>("<xmlattr>", "default");
+      for (const auto& subnode : interface.second.get_child("<xmlattr>")) {
+        if (subnode.first == "name") {
+          auto t = subnode.second.get("", "unknown");
+          values.emplace_back(std::move(t));
+        }
+      }
+    }
+  }
+  return values;
+}
+
+sensor_values read_sensor_values() {
+  sensor_values values;
+  DBusError err;
+
+  int ret;
+  bool stat;
+  dbus_uint32_t level;
+
+  // initialiset the errors
+  dbus_error_init(&err);
+
+  // connect to the system bus and check for errors
+  DBusConnection* conn = dbus_bus_get(DBUS_BUS_SYSTEM, &err);
+  if (dbus_error_is_set(&err)) {
+    fprintf(stderr, "Connection Error (%s)\n", err.message);
+    dbus_error_free(&err);
+  }
+  if (NULL == conn) {
+    exit(1);
+  }
+
+  // create a new method call and check for errors
+  DBusMessage* msg = dbus_message_new_method_call(
+      "org.openbmc.Sensors",                  // target for the method call
+      "/org/openbmc/sensors/tach",            // object to call on
+      "org.freedesktop.DBus.Introspectable",  // interface to call on
+      "Introspect");                          // method name
+  if (NULL == msg) {
+    fprintf(stderr, "Message Null\n");
+    exit(1);
+  }
+
+  DBusPendingCall* pending;
+  // send message and get a handle for a reply
+  if (!dbus_connection_send_with_reply(conn, msg, &pending,
+                                       -1)) {  // -1 is default timeout
+    fprintf(stderr, "Out Of Memory!\n");
+    exit(1);
+  }
+  if (NULL == pending) {
+    fprintf(stderr, "Pending Call Null\n");
+    exit(1);
+  }
+  dbus_connection_flush(conn);
+
+  // free message
+  dbus_message_unref(msg);
+
+  // block until we recieve a reply
+  dbus_pending_call_block(pending);
+
+  // get the reply message
+  msg = dbus_pending_call_steal_reply(pending);
+  if (NULL == msg) {
+    fprintf(stderr, "Reply Null\n");
+    exit(1);
+  }
+  // free the pending message handle
+  dbus_pending_call_unref(pending);
+
+  // read the parameters
+  DBusMessageIter args;
+  char* xml_struct = NULL;
+  if (!dbus_message_iter_init(msg, &args)) {
+    fprintf(stderr, "Message has no arguments!\n");
+  }
+
+  // read the arguments
+  if (!dbus_message_iter_init(msg, &args)) {
+    fprintf(stderr, "Message has no arguments!\n");
+  } else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) {
+    fprintf(stderr, "Argument is not string!\n");
+  } else {
+    dbus_message_iter_get_basic(&args, &xml_struct);
+  }
+  std::vector<std::string> methods;
+  if (xml_struct != NULL) {
+    std::string xml_data(xml_struct);
+    methods = read_dbus_xml_names(xml_data);
+  }
+
+  fprintf(stdout, "Found %ld sensors \n", methods.size());
+
+  for (auto& method : methods) {
+    // TODO(Ed) make sure sensor exposes SensorValue interface
+    // create a new method call and check for errors
+    DBusMessage* msg = dbus_message_new_method_call(
+        "org.openbmc.Sensors",  // target for the method call
+        ("/org/openbmc/sensors/tach/" + method).c_str(),  // object to call on
+        "org.openbmc.SensorValue",  // interface to call on
+        "getValue");                // method name
+    if (NULL == msg) {
+      fprintf(stderr, "Message Null\n");
+      exit(1);
+    }
+
+    DBusPendingCall* pending;
+    // send message and get a handle for a reply
+    if (!dbus_connection_send_with_reply(conn, msg, &pending,
+                                         -1)) {  // -1 is default timeout
+      fprintf(stderr, "Out Of Memory!\n");
+      exit(1);
+    }
+    if (NULL == pending) {
+      fprintf(stderr, "Pending Call Null\n");
+      exit(1);
+    }
+    dbus_connection_flush(conn);
+
+    // free message
+    dbus_message_unref(msg);
+
+    // block until we recieve a reply
+    dbus_pending_call_block(pending);
+
+    // get the reply message
+    msg = dbus_pending_call_steal_reply(pending);
+    if (NULL == msg) {
+      fprintf(stderr, "Reply Null\n");
+      exit(1);
+    }
+    // free the pending message handle
+    dbus_pending_call_unref(pending);
+
+    // read the parameters
+    DBusMessageIter args;
+    int32_t value;
+    if (!dbus_message_iter_init(msg, &args)) {
+      fprintf(stderr, "Message has no arguments!\n");
+    }
+
+    // read the arguments
+    if (!dbus_message_iter_init(msg, &args)) {
+      fprintf(stderr, "Message has no arguments!\n");
+    } else if (DBUS_TYPE_VARIANT != dbus_message_iter_get_arg_type(&args)) {
+      fprintf(stderr, "Argument is not string!\n");
+    } else {
+      DBusMessageIter sub;
+      dbus_message_iter_recurse(&args, &sub);
+      auto type = dbus_message_iter_get_arg_type(&sub);
+      if (DBUS_TYPE_INT32 != type) {
+        fprintf(stderr, "Variant subType is not int32 it is %d\n", type);
+      } else {
+        dbus_message_iter_get_basic(&sub, &value);
+        values.emplace_back(method.c_str(), value);
+      }
+    }
+  }
+
+  // free reply and close connection
+  dbus_message_unref(msg);
+  return values;
+}
+
 int main(int argc, char** argv) {
   auto worker(g3::LogWorker::createLogWorker());
   std::string logger_name("bmcweb");
@@ -114,6 +299,18 @@
         conn.send_binary(str);
 
       });
+
+  CROW_ROUTE(app, "/sensortest")
+  ([]() {
+    crow::json::wvalue j;
+    auto values = read_sensor_values();
+    for (auto& pair : values) {
+      j[pair.first] = pair.second;
+    }
+
+    return j;
+  });
+
   auto ssl_context = ensuressl::get_ssl_context(ssl_pem_file);
   app.port(18080)
       //.ssl(std::move(ssl_context))