diff --git a/dbus-top/sensorhelper.hpp b/dbus-top/sensorhelper.hpp
new file mode 100644
index 0000000..a619c4a
--- /dev/null
+++ b/dbus-top/sensorhelper.hpp
@@ -0,0 +1,342 @@
+// Copyright 2021 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma once
+
+#include "main.hpp"
+// This is the form a sensor assumes on DBus.
+// Aggregates their view from all other daemons.
+#include <bitset>
+#include <optional>
+#include <set>
+#include <string>
+#include <unordered_map>
+#include <unordered_set>
+#include <vector>
+// Where is this sensor seen?
+constexpr int VISIBILITY_OBJECT_MAPPER = 0;
+constexpr int VISIBILITY_HWMON = 1;
+constexpr int VISIBILITY_IPMITOOL_SDR = 2;
+class DBusConnection
+{
+  public:
+    std::string service;    // example: "systemd-resolved"
+    std::string connection; // example: ":1.1"
+    std::string cmd;        // the comm line
+    std::string unit;       // example: "systemd-resolved.service"
+    int pid;
+    // For actual DBus capture: service name, connection name, command line,
+    //                          systmed unit and PID are all known
+    DBusConnection(const std::string& _s, const std::string& _c,
+                   const std::string& _cmd, const std::string& _u, int _pid)
+    {
+        service = _s;
+        connection = _c;
+        cmd = _cmd;
+        unit = _u;
+        pid = _pid;
+    }
+
+    // During PCap replay: only service name, connection name, and PID are known
+    //                     cmd and unit are not known since they are not
+    //                     stored in the PCap file
+    DBusConnection(const std::string& _s, const std::string& _c, int _pid)
+    {
+        service = _s;
+        connection = _c;
+        pid = _pid;
+    }
+};
+
+class DBusConnectionSnapshot
+{
+  public:
+    std::vector<DBusConnection*> connections_;
+    std::unordered_map<std::string, DBusConnection*> unique_name_to_cxn;
+    DBusConnection* FindDBusConnectionByService(const std::string& service)
+    {
+        for (DBusConnection* cxn : connections_)
+        {
+            if (cxn->service == service)
+                return cxn;
+        }
+        return nullptr;
+    }
+
+    void SetConnectionPID(const std::string& connection, int pid)
+    {
+        DBusConnection* cxn = FindDBusConnectionByService(connection);
+        if (cxn != nullptr)
+        {
+            cxn->pid = pid;
+            unique_name_to_cxn[connection] = cxn; // Just to make sure
+        }
+    }
+
+    void SetConnectionUniqueName(const std::string& service,
+                                 const std::string& unique_name)
+    {
+        DBusConnection* cxn = FindDBusConnectionByService(service);
+        if (cxn != nullptr)
+        {
+            cxn->connection = unique_name;
+            unique_name_to_cxn[unique_name] = cxn;
+        }
+    }
+
+    DBusConnection* FindDBusConnectionByConnection(const std::string& conn)
+    {
+        for (DBusConnection* cxn : connections_)
+        {
+            if (cxn->connection == conn)
+                return cxn;
+        }
+        return nullptr;
+    }
+
+
+    // Only when service is known (during playback)
+    void AddConnection(const std::string& _s)
+    {
+        connections_.push_back(new DBusConnection(_s, "", "", "", INVALID));
+    }
+
+    // When all 5 pieces of details are known (during actual capture)
+    void AddConnection(const std::string& _s, const std::string& _connection,
+                       const std::string& _cmd, const std::string& _unit,
+                       int _pid)
+    {
+        DBusConnection* cxn =
+            new DBusConnection(_s, _connection, _cmd, _unit, _pid);
+        connections_.push_back(cxn);
+        unique_name_to_cxn[_connection] = cxn;
+    }
+
+    int GetConnectionPIDFromNameOrUniqueName(const std::string& key)
+    {
+        if (unique_name_to_cxn.find(key) == unique_name_to_cxn.end())
+        {
+            return INVALID;
+        }
+        else
+        {
+            return unique_name_to_cxn[key]->pid;
+        }
+    }
+
+    std::string GetConnectionCMDFromNameOrUniqueName(const std::string& key)
+    {
+        if (unique_name_to_cxn.find(key) == unique_name_to_cxn.end())
+        {
+            return "(unknown)";
+        }
+        else
+        {
+            return unique_name_to_cxn[key]->cmd;
+        }
+    }
+
+    std::string GetUniqueNameIfExists(const std::string service)
+    {
+        for (DBusConnection* cxn : connections_)
+        {
+            if (cxn->service == service)
+                return cxn->connection;
+        }
+        return service;
+    }
+
+};
+
+// Each sensor might have different units, for example current and voltage
+class Sensor
+{
+  public:
+    DBusConnection* connection_;
+    // Example: "/xyz/openbmc_project/sensors/temperature/powerseq_temp"
+    std::string object_path_;
+    std::string SensorID()
+    {
+        const size_t idx = object_path_.rfind('/');
+        if (idx != std::string::npos)
+        {
+            return object_path_.substr(idx + 1);
+        }
+        else
+            return ("unknown sensor");
+    }
+
+    std::string ServiceName()
+    {
+        if (connection_ == nullptr)
+            return "";
+        else
+            return connection_->service;
+    }
+
+    std::string ConnectionName()
+    {
+        if (connection_ == nullptr)
+            return "";
+        else
+            return connection_->connection;
+    }
+
+    std::string ObjectPath()
+    {
+        return object_path_;
+    }
+
+    // Should contain the following:
+    // 1. "org.freedesktop.DBus.Introspectable"
+    // 2. "org.freedesktop.DBus.Peer"
+    // 3. "org.freedesktop.DBus.Properties"
+    // 4. "xyz.openbmc_project.Sensor.Value"
+    // 5. "xyz.openbmc_project.State.Decorator.OperationalStatus"
+    std::set<std::string> interfaces_;
+    std::bitset<4> visibility_flags_;
+    std::set<std::string> associations_;
+};
+
+class SensorSnapshot
+{
+  public:
+    std::vector<std::string> GetDistinctSensorNames()
+    {
+        std::unordered_set<std::string> seen;
+        std::vector<std::string> ret;
+        for (Sensor* s : sensors_)
+        {
+            std::string sn = s->SensorID();
+            if (seen.find(sn) == seen.end())
+            {
+                ret.push_back(sn);
+                seen.insert(sn);
+            }
+        }
+        return ret;
+    }
+
+    explicit SensorSnapshot(DBusConnectionSnapshot* cs)
+    {
+        connection_snapshot_ = cs;
+    }
+
+    ~SensorSnapshot()
+    {
+        for (Sensor* s : sensors_)
+        {
+            delete s;
+        }
+    }
+
+    int SensorCount()
+    {
+        return int(sensors_.size());
+    }
+
+    Sensor* FindOrCreateSensorByServiceAndObject(const std::string& service,
+                                                 const std::string& object)
+    {
+        Sensor* ret = nullptr;
+        for (Sensor* s : sensors_)
+        {
+            if (s->ServiceName() == service && s->object_path_ == object)
+            {
+                ret = s;
+                break;
+            }
+        }
+        if (ret == nullptr)
+        {
+            DBusConnection* cxn =
+                connection_snapshot_->FindDBusConnectionByService(service);
+            ret = new Sensor();
+            ret->connection_ = cxn;
+            ret->object_path_ = object;
+            sensors_.push_back(ret);
+        }
+        return ret;
+    }
+
+    // Note: one sensor_id might correspond to multiple sensors.
+    // Example: "VDD" can have all 3 of power, current and voltage.
+    std::vector<Sensor*> FindSensorsBySensorID(const std::string& sensor_id)
+    {
+        std::vector<Sensor*> ret;
+        for (Sensor* s : sensors_)
+        {
+            const std::string& p = s->object_path_;
+            if (p.find(sensor_id) == p.size() - sensor_id.size())
+            {
+                ret.push_back(s);
+            }
+        }
+        return ret;
+    }
+
+    // This sensor is visible from Object Mapper
+    void SerSensorVisibleFromObjectMapper(const std::string& service,
+                                          const std::string& object)
+    {
+        Sensor* s = FindOrCreateSensorByServiceAndObject(service, object);
+        s->visibility_flags_.set(VISIBILITY_OBJECT_MAPPER);
+    }
+    
+    // This sensor is visible from Hwmon
+    void SetSensorVisibleFromHwmon(const std::string& service,
+                                   const std::string& object)
+    {
+        Sensor* s = FindOrCreateSensorByServiceAndObject(service, object);
+        s->visibility_flags_.set(VISIBILITY_HWMON);
+    }
+
+    // This sensor is visible from `ipmitool sdr`
+    // The first column is referred to as "sensorid".
+    void SetSensorVisibleFromIpmitoolSdr(const std::string& sensor_id)
+    {
+        std::vector<Sensor*> sensors = FindSensorsBySensorID(sensor_id);
+        for (Sensor* s : sensors)
+            s->visibility_flags_.set(VISIBILITY_IPMITOOL_SDR);
+    }
+
+    void PrintSummary()
+    {
+        for (Sensor* s : sensors_)
+        {
+            printf("%50s %50s %9s\n", s->ServiceName().c_str(),
+                   s->object_path_.c_str(),
+                   s->visibility_flags_.to_string().c_str());
+        }
+    }
+
+    Sensor* FindSensorByDBusUniqueNameOrServiceName(const std::string& key)
+    {
+        for (Sensor* s : sensors_)
+        {
+            if (s->ConnectionName() == key || s->ServiceName() == key)
+                return s;
+        }
+        return nullptr;
+    }
+
+  private:
+    std::vector<Sensor*> sensors_;
+    std::unordered_map<std::string, int> conn2pid_;
+    DBusConnectionSnapshot* connection_snapshot_;
+};
+
+bool IsSensorObjectPath(const std::string& s);
+bool IsUniqueName(const std::string& x);
+std::string Trim(const std::string& s);
