diff --git a/src/IpmbSensor.cpp b/src/IpmbSensor.cpp
new file mode 100644
index 0000000..71d4a5b
--- /dev/null
+++ b/src/IpmbSensor.cpp
@@ -0,0 +1,377 @@
+/*
+// Copyright (c) 2019 Intel Corporation
+//
+// 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.
+*/
+
+#include "IpmbSensor.hpp"
+
+#include "Utils.hpp"
+#include "VariantVisitors.hpp"
+
+#include <math.h>
+
+#include <boost/algorithm/string.hpp>
+#include <boost/algorithm/string/predicate.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <chrono>
+#include <iostream>
+#include <limits>
+#include <numeric>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+#include <vector>
+
+constexpr const bool debug = false;
+
+constexpr const char* configInterface =
+    "xyz.openbmc_project.Configuration.IpmbSensor";
+static constexpr double ipmbMaxReading = 0xFF;
+static constexpr double ipmbMinReading = 0;
+
+static constexpr uint8_t meAddress = 1;
+static constexpr uint8_t lun = 0;
+
+using IpmbMethodType =
+    std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>>;
+
+IpmbSensor::IpmbSensor(std::shared_ptr<sdbusplus::asio::connection>& conn,
+                       boost::asio::io_service& io,
+                       const std::string& sensorName,
+                       const std::string& sensorConfiguration,
+                       sdbusplus::asio::object_server& objectServer,
+                       std::vector<thresholds::Threshold>&& thresholdData,
+                       uint8_t deviceAddress) :
+    Sensor(boost::replace_all_copy(sensorName, " ", "_"),
+           "" /* todo: remove arg from base*/, std::move(thresholdData),
+           sensorConfiguration, "xyz.openbmc_project.Configuration.ExitAirTemp",
+           ipmbMaxReading, ipmbMinReading),
+    objectServer(objectServer), dbusConnection(conn), waitTimer(io),
+    deviceAddress(deviceAddress)
+{
+    sensorInterface = objectServer.add_interface(
+        "/xyz/openbmc_project/sensors/temperature/" + name,
+        "xyz.openbmc_project.Sensor.Value");
+
+    if (thresholds::hasWarningInterface(thresholds))
+    {
+        thresholdInterfaceWarning = objectServer.add_interface(
+            "/xyz/openbmc_project/sensors/temperature/" + name,
+            "xyz.openbmc_project.Sensor.Threshold.Warning");
+    }
+    if (thresholds::hasCriticalInterface(thresholds))
+    {
+        thresholdInterfaceCritical = objectServer.add_interface(
+            "/xyz/openbmc_project/sensors/temperature/" + name,
+            "xyz.openbmc_project.Sensor.Threshold.Critical");
+    }
+    setupPowerMatch(conn);
+}
+
+IpmbSensor::~IpmbSensor()
+{
+    waitTimer.cancel();
+    objectServer.remove_interface(thresholdInterfaceWarning);
+    objectServer.remove_interface(thresholdInterfaceCritical);
+    objectServer.remove_interface(sensorInterface);
+}
+
+void IpmbSensor::init(void)
+{
+    setInitialProperties(dbusConnection);
+    loadDefaults();
+    if (initCommand)
+    {
+        dbusConnection->async_method_call(
+            [this](boost::system::error_code ec,
+                   const IpmbMethodType& response) {
+                const int& status = std::get<0>(response);
+
+                if (ec || status)
+                {
+                    std::cerr
+                        << "Error setting init command for device: " << name
+                        << "\n";
+                }
+                read();
+            },
+            "xyz.openbmc_project.Ipmi.Channel.Ipmb",
+            "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
+            "sendRequest", commandAddress, netfn, lun, *initCommand, initData);
+    }
+    else
+    {
+        read();
+    }
+}
+
+void IpmbSensor::loadDefaults()
+{
+    if (type == IpmbType::meSensor)
+    {
+        commandAddress = meAddress;
+        netfn = 0x4;    // sensor
+        command = 0x2d; // get sensor reading
+        commandData = {deviceAddress};
+    }
+    else if (type == IpmbType::PXE1410CVR)
+    {
+        commandAddress = meAddress;
+        netfn = 0x2e;       // me bridge
+        command = 0xd9;     // send raw pmbus
+        initCommand = 0xd9; // send raw pmbus
+        commandData = {0x57, 0x01, 0x00, 0x16, 0x03, deviceAddress, 00,
+                       0x00, 0x00, 0x00, 0x01, 0x02, 0x29};
+        initData = {0x57, 0x01, 0x00, 0x14, 0x03, deviceAddress, 0x00,
+                    0x00, 0x00, 0x00, 0x02, 0x00, 0x00,          0x60};
+    }
+    else if (type == IpmbType::IR38363VR)
+    {
+        commandAddress = meAddress;
+        netfn = 0x2e;   // me bridge
+        command = 0xd9; // send raw pmbus
+        commandData = {0x57, 0x01, 0x00, 0x16, 0x03, deviceAddress, 00,
+                       0x00, 0x00, 0x00, 0x01, 0x02, 0x8D};
+    }
+    else if (type == IpmbType::mpsVR)
+    {
+        commandAddress = meAddress;
+        netfn = 0x2e;       // me bridge
+        command = 0xd9;     // send raw pmbus
+        initCommand = 0xd9; // send raw pmbus
+        commandData = {0x57, 0x01, 0x00, 0x16, 0x3,  deviceAddress, 0x00,
+                       0x00, 0x00, 0x00, 0x01, 0x02, 0x8d};
+        initData = {0x57, 0x01, 0x00, 0x14, 0x03, deviceAddress, 0x00,
+                    0x00, 0x00, 0x00, 0x02, 0x00, 0x00,          0x00};
+    }
+    else
+    {
+        throw std::runtime_error("Invalid sensor type");
+    }
+}
+
+void IpmbSensor::checkThresholds(void)
+{
+    if (readState == PowerState::on && !isPowerOn())
+    {
+        return;
+    }
+    thresholds::checkThresholds(this);
+}
+
+void IpmbSensor::read(void)
+{
+    static constexpr size_t pollTime = 1; // in seconds
+
+    waitTimer.expires_from_now(boost::posix_time::seconds(pollTime));
+    waitTimer.async_wait([this](const boost::system::error_code& ec) {
+        if (ec == boost::asio::error::operation_aborted)
+        {
+            return; // we're being canceled
+        }
+        if (!isPowerOn() && readState == PowerState::on)
+        {
+            updateValue(0);
+            read();
+            return;
+        }
+        dbusConnection->async_method_call(
+            [this](boost::system::error_code ec,
+                   const IpmbMethodType& response) {
+                const int& status = std::get<0>(response);
+                if (ec || status)
+                {
+                    std::cerr << "Error reading from device: " << name << "\n";
+                    updateValue(0);
+                    read();
+                    return;
+                }
+                if (!isPowerOn() && readState == PowerState::on)
+                {
+                    updateValue(0);
+                    read();
+                    return;
+                }
+                const std::vector<uint8_t>& data = std::get<5>(response);
+                if constexpr (debug)
+                {
+                    std::cout << name << ": ";
+                    for (size_t d : data)
+                    {
+                        std::cout << d << " ";
+                    }
+                    std::cout << "\n";
+                }
+                uint16_t value = 0;
+                if (type == IpmbType::meSensor)
+                {
+                    if (data.empty())
+                    {
+                        std::cerr << "Invalid data from device: " << name
+                                  << "\n";
+                        read();
+                        return;
+                    }
+                    value = data[0];
+                }
+                else if (type == IpmbType::PXE1410CVR ||
+                         type == IpmbType::IR38363VR)
+                {
+                    if (data.size() < 4)
+                    {
+                        std::cerr << "Invalid data from device: " << name
+                                  << "\n";
+                        read();
+                        return;
+                    }
+                    // format based on the 11 bit linear data format
+                    value = ((data[4] << 8) | data[3]) >> 3;
+                }
+                else if (type == IpmbType::mpsVR)
+                {
+                    if (data.size() < 4)
+                    {
+                        std::cerr << "Invalid data from device: " << name
+                                  << "\n";
+                        read();
+                        return;
+                    }
+                    value = data[3];
+                }
+                else
+                {
+                    throw std::runtime_error("Invalid sensor type");
+                }
+                updateValue(value);
+                read();
+            },
+            "xyz.openbmc_project.Ipmi.Channel.Ipmb",
+            "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
+            "sendRequest", commandAddress, netfn, lun, command, commandData);
+    });
+}
+void createSensors(
+    boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
+    boost::container::flat_map<std::string, std::unique_ptr<IpmbSensor>>&
+        sensors,
+    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
+{
+    if (!dbusConnection)
+    {
+        std::cerr << "Connection not created\n";
+        return;
+    }
+    dbusConnection->async_method_call(
+        [&](boost::system::error_code ec, const ManagedObjectType& resp) {
+            if (ec)
+            {
+                std::cerr << "Error contacting entity manager\n";
+                return;
+            }
+            for (const auto& pathPair : resp)
+            {
+                for (const auto& entry : pathPair.second)
+                {
+                    if (entry.first != configInterface)
+                    {
+                        continue;
+                    }
+                    std::string name =
+                        loadVariant<std::string>(entry.second, "Name");
+
+                    std::vector<thresholds::Threshold> sensorThresholds;
+                    if (!parseThresholdsFromConfig(pathPair.second,
+                                                   sensorThresholds))
+                    {
+                        std::cerr << "error populating thresholds for " << name
+                                  << "\n";
+                    }
+                    uint8_t deviceAddress =
+                        loadVariant<uint8_t>(entry.second, "Address");
+
+                    std::string sensorClass =
+                        loadVariant<std::string>(entry.second, "Class");
+                    auto& sensor = sensors[name];
+                    sensor = std::make_unique<IpmbSensor>(
+                        dbusConnection, io, name, pathPair.first, objectServer,
+                        std::move(sensorThresholds), deviceAddress);
+
+                    if (sensorClass == "PxeBridgeTemp")
+                    {
+                        sensor->type = IpmbType::PXE1410CVR;
+                    }
+                    else if (sensorClass == "IRBridgeTemp")
+                    {
+                        sensor->type = IpmbType::IR38363VR;
+                    }
+                    else if (sensorClass == "MpsBridgeTemp")
+                    {
+                        sensor->type = IpmbType::mpsVR;
+                    }
+                    else if (sensorClass == "METemp")
+                    {
+                        sensor->type = IpmbType::meSensor;
+                    }
+                    else
+                    {
+                        std::cerr << "Invalid class " << sensorClass << "\n";
+                        continue;
+                    }
+                    sensor->init();
+                }
+            }
+        },
+        entityManagerName, "/", "org.freedesktop.DBus.ObjectManager",
+        "GetManagedObjects");
+}
+
+int main(int argc, char** argv)
+{
+
+    boost::asio::io_service io;
+    auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
+    systemBus->request_name("xyz.openbmc_project.IpmbSensor");
+    sdbusplus::asio::object_server objectServer(systemBus);
+    boost::container::flat_map<std::string, std::unique_ptr<IpmbSensor>>
+        sensors;
+
+    io.post([&]() { createSensors(io, objectServer, sensors, systemBus); });
+
+    boost::asio::deadline_timer configTimer(io);
+
+    std::function<void(sdbusplus::message::message&)> eventHandler =
+        [&](sdbusplus::message::message& message) {
+            configTimer.expires_from_now(boost::posix_time::seconds(1));
+            // create a timer because normally multiple properties change
+            configTimer.async_wait([&](const boost::system::error_code& ec) {
+                if (ec == boost::asio::error::operation_aborted)
+                {
+                    return; // we're being canceled
+                }
+                createSensors(io, objectServer, sensors, systemBus);
+                if (sensors.empty())
+                {
+                    std::cout << "Configuration not detected\n";
+                }
+            });
+        };
+
+    sdbusplus::bus::match::match match(
+        static_cast<sdbusplus::bus::bus&>(*systemBus),
+        "type='signal',member='PropertiesChanged',path_namespace='" +
+            std::string(inventoryPath) + "',arg0namespace='" + configInterface +
+            "'",
+        eventHandler);
+
+    io.run();
+}
