diff --git a/src/psu/PSUEvent.cpp b/src/psu/PSUEvent.cpp
new file mode 100644
index 0000000..438faa2
--- /dev/null
+++ b/src/psu/PSUEvent.cpp
@@ -0,0 +1,379 @@
+/*
+// 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 "PSUEvent.hpp"
+
+#include "SensorPaths.hpp"
+#include "Utils.hpp"
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/random_access_file.hpp>
+#include <boost/container/flat_map.hpp>
+#include <phosphor-logging/lg2.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <array>
+#include <chrono>
+#include <cstddef>
+#include <iostream>
+#include <memory>
+#include <set>
+#include <stdexcept>
+#include <string>
+#include <utility>
+#include <vector>
+
+PSUCombineEvent::PSUCombineEvent(
+    sdbusplus::asio::object_server& objectServer,
+    std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::io_context& io, const std::string& psuName,
+    const PowerState& powerState, EventPathList& eventPathList,
+    GroupEventPathList& groupEventPathList, const std::string& combineEventName,
+    double pollRate) : objServer(objectServer)
+{
+    std::string psuNameEscaped = sensor_paths::escapePathForDbus(psuName);
+    eventInterface = objServer.add_interface(
+        "/xyz/openbmc_project/State/Decorator/" + psuNameEscaped + "_" +
+            combineEventName,
+        "xyz.openbmc_project.State.Decorator.OperationalStatus");
+    eventInterface->register_property("functional", true);
+
+    if (!eventInterface->initialize())
+    {
+        std::cerr << "error initializing event interface\n";
+    }
+
+    std::shared_ptr<std::set<std::string>> combineEvent =
+        std::make_shared<std::set<std::string>>();
+    for (const auto& [eventName, paths] : eventPathList)
+    {
+        std::shared_ptr<std::set<std::string>> assert =
+            std::make_shared<std::set<std::string>>();
+        std::shared_ptr<bool> state = std::make_shared<bool>(false);
+
+        std::string eventPSUName = eventName + psuName;
+        for (const auto& path : paths)
+        {
+            auto p = std::make_shared<PSUSubEvent>(
+                eventInterface, path, conn, io, powerState, eventName,
+                eventName, assert, combineEvent, state, psuName, pollRate);
+            p->setupRead();
+
+            events[eventPSUName].emplace_back(p);
+            asserts.emplace_back(assert);
+            states.emplace_back(state);
+        }
+    }
+
+    for (const auto& [eventName, groupEvents] : groupEventPathList)
+    {
+        for (const auto& [groupEventName, paths] : groupEvents)
+        {
+            std::shared_ptr<std::set<std::string>> assert =
+                std::make_shared<std::set<std::string>>();
+            std::shared_ptr<bool> state = std::make_shared<bool>(false);
+
+            std::string eventPSUName = groupEventName + psuName;
+            for (const auto& path : paths)
+            {
+                auto p = std::make_shared<PSUSubEvent>(
+                    eventInterface, path, conn, io, powerState, groupEventName,
+                    eventName, assert, combineEvent, state, psuName, pollRate);
+                p->setupRead();
+                events[eventPSUName].emplace_back(p);
+
+                asserts.emplace_back(assert);
+                states.emplace_back(state);
+            }
+        }
+    }
+}
+
+PSUCombineEvent::~PSUCombineEvent()
+{
+    // Clear unique_ptr first
+    for (auto& [psuName, subEvents] : events)
+    {
+        for (auto& subEventPtr : subEvents)
+        {
+            subEventPtr.reset();
+        }
+    }
+    events.clear();
+    objServer.remove_interface(eventInterface);
+}
+
+static boost::container::flat_map<std::string,
+                                  std::pair<std::string, std::string>>
+    logID = {
+        {"PredictiveFailure",
+         {"OpenBMC.0.1.PowerSupplyFailurePredicted",
+          "OpenBMC.0.1.PowerSupplyPredictedFailureRecovered"}},
+        {"Failure",
+         {"OpenBMC.0.1.PowerSupplyFailed", "OpenBMC.0.1.PowerSupplyRecovered"}},
+        {"ACLost",
+         {"OpenBMC.0.1.PowerSupplyPowerLost",
+          "OpenBMC.0.1.PowerSupplyPowerRestored"}},
+        {"FanFault",
+         {"OpenBMC.0.1.PowerSupplyFanFailed",
+          "OpenBMC.0.1.PowerSupplyFanRecovered"}},
+        {"ConfigureError",
+         {"OpenBMC.0.1.PowerSupplyConfigurationError",
+          "OpenBMC.0.1.PowerSupplyConfigurationErrorRecovered"}}};
+
+PSUSubEvent::PSUSubEvent(
+    std::shared_ptr<sdbusplus::asio::dbus_interface> eventInterface,
+    const std::string& path, std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::io_context& io, const PowerState& powerState,
+    const std::string& groupEventName, const std::string& eventName,
+    std::shared_ptr<std::set<std::string>> asserts,
+    std::shared_ptr<std::set<std::string>> combineEvent,
+    std::shared_ptr<bool> state, const std::string& psuName, double pollRate) :
+    eventInterface(std::move(eventInterface)), asserts(std::move(asserts)),
+    combineEvent(std::move(combineEvent)), assertState(std::move(state)),
+    path(path), eventName(eventName), readState(powerState), waitTimer(io),
+
+    inputDev(io, path, boost::asio::random_access_file::read_only),
+    psuName(psuName), groupEventName(groupEventName), systemBus(conn)
+{
+    buffer = std::make_shared<std::array<char, 128>>();
+    if (pollRate > 0.0)
+    {
+        eventPollMs = static_cast<unsigned int>(pollRate * 1000);
+    }
+
+    auto found = logID.find(eventName);
+    if (found == logID.end())
+    {
+        assertMessage.clear();
+        deassertMessage.clear();
+    }
+    else
+    {
+        assertMessage = found->second.first;
+        deassertMessage = found->second.second;
+    }
+
+    auto fanPos = path.find("fan");
+    if (fanPos != std::string::npos)
+    {
+        fanName = path.substr(fanPos);
+        auto fanNamePos = fanName.find('_');
+        if (fanNamePos != std::string::npos)
+        {
+            fanName = fanName.substr(0, fanNamePos);
+        }
+    }
+}
+
+PSUSubEvent::~PSUSubEvent()
+{
+    waitTimer.cancel();
+    inputDev.close();
+}
+
+void PSUSubEvent::setupRead()
+{
+    if (!readingStateGood(readState))
+    {
+        // Deassert the event
+        updateValue(0);
+        restartRead();
+        return;
+    }
+    if (!buffer)
+    {
+        std::cerr << "Buffer was invalid?";
+        return;
+    }
+
+    std::weak_ptr<PSUSubEvent> weakRef = weak_from_this();
+    inputDev.async_read_some_at(
+        0, boost::asio::buffer(buffer->data(), buffer->size() - 1),
+        [weakRef, buffer{buffer}](const boost::system::error_code& ec,
+                                  std::size_t bytesTransferred) {
+            std::shared_ptr<PSUSubEvent> self = weakRef.lock();
+            if (self)
+            {
+                self->handleResponse(ec, bytesTransferred);
+            }
+        });
+}
+
+void PSUSubEvent::restartRead()
+{
+    std::weak_ptr<PSUSubEvent> weakRef = weak_from_this();
+    waitTimer.expires_after(std::chrono::milliseconds(eventPollMs));
+    waitTimer.async_wait([weakRef](const boost::system::error_code& ec) {
+        if (ec == boost::asio::error::operation_aborted)
+        {
+            return;
+        }
+        std::shared_ptr<PSUSubEvent> self = weakRef.lock();
+        if (self)
+        {
+            self->setupRead();
+        }
+    });
+}
+
+void PSUSubEvent::handleResponse(const boost::system::error_code& err,
+                                 size_t bytesTransferred)
+{
+    if (err == boost::asio::error::operation_aborted)
+    {
+        return;
+    }
+
+    if ((err == boost::system::errc::bad_file_descriptor) ||
+        (err == boost::asio::error::misc_errors::not_found))
+    {
+        return;
+    }
+    if (!buffer)
+    {
+        std::cerr << "Buffer was invalid?";
+        return;
+    }
+    // null terminate the string so we don't walk off the end
+    std::array<char, 128>& bufferRef = *buffer;
+    bufferRef[bytesTransferred] = '\0';
+
+    if (!err)
+    {
+        try
+        {
+            int nvalue = std::stoi(bufferRef.data());
+            updateValue(nvalue);
+            errCount = 0;
+        }
+        catch (const std::invalid_argument&)
+        {
+            errCount++;
+        }
+    }
+    else
+    {
+        errCount++;
+    }
+    if (errCount >= warnAfterErrorCount)
+    {
+        if (errCount == warnAfterErrorCount)
+        {
+            std::cerr << "Failure to read event at " << path << "\n";
+        }
+        updateValue(0);
+        errCount++;
+    }
+    restartRead();
+}
+
+// Any of the sub events of one event is asserted, then the event will be
+// asserted. Only if none of the sub events are asserted, the event will be
+// deasserted.
+void PSUSubEvent::updateValue(const int& newValue)
+{
+    // Take no action if value already equal
+    // Same semantics as Sensor::updateValue(const double&)
+    if (newValue == value)
+    {
+        return;
+    }
+
+    if (newValue == 0)
+    {
+        // log deassert only after all asserts are gone
+        if (!(*asserts).empty())
+        {
+            auto found = (*asserts).find(path);
+            if (found == (*asserts).end())
+            {
+                return;
+            }
+            (*asserts).erase(path);
+
+            return;
+        }
+        if (*assertState)
+        {
+            *assertState = false;
+            auto foundCombine = (*combineEvent).find(groupEventName);
+            if (foundCombine == (*combineEvent).end())
+            {
+                return;
+            }
+            (*combineEvent).erase(groupEventName);
+            if (!deassertMessage.empty())
+            {
+                // Fan Failed has two args
+                if (deassertMessage == "OpenBMC.0.1.PowerSupplyFanRecovered")
+                {
+                    lg2::info("{EVENT} deassert", "EVENT", eventName,
+                              "REDFISH_MESSAGE_ID", deassertMessage,
+                              "REDFISH_MESSAGE_ARGS",
+                              (psuName + ',' + fanName));
+                }
+                else
+                {
+                    lg2::info("{EVENT} deassert", "EVENT", eventName,
+                              "REDFISH_MESSAGE_ID", deassertMessage,
+                              "REDFISH_MESSAGE_ARGS", psuName);
+                }
+            }
+
+            if ((*combineEvent).empty())
+            {
+                eventInterface->set_property("functional", true);
+            }
+        }
+    }
+    else
+    {
+        std::cerr << "PSUSubEvent asserted by " << path << "\n";
+
+        if ((!*assertState) && ((*asserts).empty()))
+        {
+            *assertState = true;
+            if (!assertMessage.empty())
+            {
+                // Fan Failed has two args
+                if (assertMessage == "OpenBMC.0.1.PowerSupplyFanFailed")
+                {
+                    lg2::warning("{EVENT} assert", "EVENT", eventName,
+                                 "REDFISH_MESSAGE_ID", assertMessage,
+                                 "REDFISH_MESSAGE_ARGS",
+                                 (psuName + ',' + fanName));
+                }
+                else
+                {
+                    lg2::warning("{EVENT} assert", "EVENT", eventName,
+                                 "REDFISH_MESSAGE_ID", assertMessage,
+                                 "REDFISH_MESSAGE_ARGS", psuName);
+                }
+            }
+            if ((*combineEvent).empty())
+            {
+                eventInterface->set_property("functional", false);
+            }
+            (*combineEvent).emplace(groupEventName);
+        }
+        (*asserts).emplace(path);
+    }
+    value = newValue;
+}
diff --git a/src/psu/PSUEvent.hpp b/src/psu/PSUEvent.hpp
new file mode 100644
index 0000000..d761f45
--- /dev/null
+++ b/src/psu/PSUEvent.hpp
@@ -0,0 +1,101 @@
+/*
+// 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.
+*/
+
+#pragma once
+
+#include "Utils.hpp"
+
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/random_access_file.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/container/flat_map.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <array>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+using EventPathList =
+    boost::container::flat_map<std::string, std::vector<std::string>>;
+using GroupEventPathList =
+    boost::container::flat_map<std::string, EventPathList>;
+
+class PSUSubEvent : public std::enable_shared_from_this<PSUSubEvent>
+{
+  public:
+    PSUSubEvent(std::shared_ptr<sdbusplus::asio::dbus_interface> eventInterface,
+                const std::string& path,
+                std::shared_ptr<sdbusplus::asio::connection>& conn,
+                boost::asio::io_context& io, const PowerState& powerState,
+                const std::string& groupEventName, const std::string& eventName,
+                std::shared_ptr<std::set<std::string>> asserts,
+                std::shared_ptr<std::set<std::string>> combineEvent,
+                std::shared_ptr<bool> state, const std::string& psuName,
+                double pollRate);
+    ~PSUSubEvent();
+
+    std::shared_ptr<sdbusplus::asio::dbus_interface> eventInterface;
+    std::shared_ptr<std::set<std::string>> asserts;
+    std::shared_ptr<std::set<std::string>> combineEvent;
+    std::shared_ptr<bool> assertState;
+    void setupRead();
+
+  private:
+    int value = 0;
+    size_t errCount{0};
+    std::string path;
+    std::string eventName;
+
+    PowerState readState;
+    boost::asio::steady_timer waitTimer;
+    std::shared_ptr<std::array<char, 128>> buffer;
+    void restartRead();
+    void handleResponse(const boost::system::error_code& err,
+                        size_t bytesTransferred);
+    void updateValue(const int& newValue);
+    boost::asio::random_access_file inputDev;
+    std::string psuName;
+    std::string groupEventName;
+    std::string fanName;
+    std::string assertMessage;
+    std::string deassertMessage;
+    std::shared_ptr<sdbusplus::asio::connection> systemBus;
+    unsigned int eventPollMs = defaultEventPollMs;
+    static constexpr unsigned int defaultEventPollMs = 1000;
+    static constexpr size_t warnAfterErrorCount = 10;
+};
+
+class PSUCombineEvent
+{
+  public:
+    PSUCombineEvent(sdbusplus::asio::object_server& objectServer,
+                    std::shared_ptr<sdbusplus::asio::connection>& conn,
+                    boost::asio::io_context& io, const std::string& psuName,
+                    const PowerState& powerState, EventPathList& eventPathList,
+                    GroupEventPathList& groupEventPathList,
+                    const std::string& combineEventName, double pollRate);
+    ~PSUCombineEvent();
+
+    sdbusplus::asio::object_server& objServer;
+    std::shared_ptr<sdbusplus::asio::dbus_interface> eventInterface;
+    boost::container::flat_map<std::string,
+                               std::vector<std::shared_ptr<PSUSubEvent>>>
+        events;
+    std::vector<std::shared_ptr<std::set<std::string>>> asserts;
+    std::vector<std::shared_ptr<bool>> states;
+};
diff --git a/src/psu/PSUSensor.cpp b/src/psu/PSUSensor.cpp
new file mode 100644
index 0000000..4d410fe
--- /dev/null
+++ b/src/psu/PSUSensor.cpp
@@ -0,0 +1,255 @@
+/*
+// 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 "PSUSensor.hpp"
+
+#include "DeviceMgmt.hpp"
+#include "SensorPaths.hpp"
+#include "Thresholds.hpp"
+#include "Utils.hpp"
+#include "sensor.hpp"
+
+#include <boost/asio/buffer.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/random_access_file.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <array>
+#include <chrono>
+#include <cstddef>
+#include <iostream>
+#include <limits>
+#include <memory>
+#include <stdexcept>
+#include <string>
+#include <utility>
+#include <vector>
+
+static constexpr const char* sensorPathPrefix = "/xyz/openbmc_project/sensors/";
+
+static constexpr bool debug = false;
+
+PSUSensor::PSUSensor(
+    const std::string& path, const std::string& objectType,
+    sdbusplus::asio::object_server& objectServer,
+    std::shared_ptr<sdbusplus::asio::connection>& conn,
+    boost::asio::io_context& io, const std::string& sensorName,
+    std::vector<thresholds::Threshold>&& thresholdsIn,
+    const std::string& sensorConfiguration, const PowerState& powerState,
+    const std::string& sensorUnits, unsigned int factor, double max, double min,
+    double offset, const std::string& label, size_t tSize, double pollRate,
+    const std::shared_ptr<I2CDevice>& i2cDevice) :
+    Sensor(escapeName(sensorName), std::move(thresholdsIn), sensorConfiguration,
+           objectType, false, false, max, min, conn, powerState),
+    i2cDevice(i2cDevice), objServer(objectServer),
+    inputDev(io, path, boost::asio::random_access_file::read_only),
+    waitTimer(io), path(path), sensorFactor(factor), sensorOffset(offset),
+    thresholdTimer(io)
+{
+    buffer = std::make_shared<std::array<char, 128>>();
+    std::string unitPath = sensor_paths::getPathForUnits(sensorUnits);
+    if constexpr (debug)
+    {
+        std::cerr << "Constructed sensor: path " << path << " type "
+                  << objectType << " config " << sensorConfiguration
+                  << " typename " << unitPath << " factor " << factor << " min "
+                  << min << " max " << max << " offset " << offset << " name \""
+                  << sensorName << "\"\n";
+    }
+    if (pollRate > 0.0)
+    {
+        sensorPollMs = static_cast<unsigned int>(pollRate * 1000);
+    }
+
+    std::string dbusPath = sensorPathPrefix + unitPath + "/" + name;
+
+    sensorInterface = objectServer.add_interface(
+        dbusPath, "xyz.openbmc_project.Sensor.Value");
+
+    for (const auto& threshold : thresholds)
+    {
+        std::string interface = thresholds::getInterface(threshold.level);
+        thresholdInterfaces[static_cast<size_t>(threshold.level)] =
+            objectServer.add_interface(dbusPath, interface);
+    }
+
+    // This should be called before initializing association.
+    // createInventoryAssoc() does add more associations before doing
+    // register and initialize "Associations" property.
+    if (label.empty() || tSize == thresholds.size())
+    {
+        setInitialProperties(sensorUnits);
+    }
+    else
+    {
+        setInitialProperties(sensorUnits, label, tSize);
+    }
+
+    association = objectServer.add_interface(dbusPath, association::interface);
+
+    createInventoryAssoc(conn, association, configurationPath);
+}
+
+PSUSensor::~PSUSensor()
+{
+    deactivate();
+
+    objServer.remove_interface(sensorInterface);
+    for (const auto& iface : thresholdInterfaces)
+    {
+        objServer.remove_interface(iface);
+    }
+    objServer.remove_interface(association);
+}
+
+bool PSUSensor::isActive()
+{
+    return inputDev.is_open();
+}
+
+void PSUSensor::activate(const std::string& newPath,
+                         const std::shared_ptr<I2CDevice>& newI2CDevice)
+{
+    if (isActive())
+    {
+        // Avoid activating an active sensor
+        return;
+    }
+    path = newPath;
+    i2cDevice = newI2CDevice;
+    inputDev.open(path, boost::asio::random_access_file::read_only);
+    markAvailable(true);
+    setupRead();
+}
+
+void PSUSensor::deactivate()
+{
+    markAvailable(false);
+    // close the input dev to cancel async operations
+    inputDev.close();
+    waitTimer.cancel();
+    i2cDevice = nullptr;
+    path = "";
+}
+
+void PSUSensor::setupRead()
+{
+    if (!readingStateGood())
+    {
+        markAvailable(false);
+        updateValue(std::numeric_limits<double>::quiet_NaN());
+        restartRead();
+        return;
+    }
+
+    if (buffer == nullptr)
+    {
+        std::cerr << "Buffer was invalid?";
+        return;
+    }
+
+    std::weak_ptr<PSUSensor> weak = weak_from_this();
+    // Note, we are building a asio buffer that is one char smaller than
+    // the actual data structure, so that we can always append the null
+    // terminator.  This can go away once std::from_chars<double> is available
+    // in the standard
+    inputDev.async_read_some_at(
+        0, boost::asio::buffer(buffer->data(), buffer->size() - 1),
+        [weak, buffer{buffer}](const boost::system::error_code& ec,
+                               size_t bytesRead) {
+            std::shared_ptr<PSUSensor> self = weak.lock();
+            if (!self)
+            {
+                return;
+            }
+
+            self->handleResponse(ec, bytesRead);
+        });
+}
+
+void PSUSensor::restartRead()
+{
+    std::weak_ptr<PSUSensor> weakRef = weak_from_this();
+    waitTimer.expires_after(std::chrono::milliseconds(sensorPollMs));
+    waitTimer.async_wait([weakRef](const boost::system::error_code& ec) {
+        if (ec == boost::asio::error::operation_aborted)
+        {
+            std::cerr << "Failed to reschedule\n";
+            return;
+        }
+        std::shared_ptr<PSUSensor> self = weakRef.lock();
+        if (self)
+        {
+            self->setupRead();
+        }
+    });
+}
+
+// Create a buffer expected to be able to hold more characters than will be
+// present in the input file.
+void PSUSensor::handleResponse(const boost::system::error_code& err,
+                               size_t bytesRead)
+{
+    if (err == boost::asio::error::operation_aborted)
+    {
+        std::cerr << "Read aborted\n";
+        return;
+    }
+    if ((err == boost::system::errc::bad_file_descriptor) ||
+        (err == boost::asio::error::misc_errors::not_found))
+    {
+        std::cerr << "Bad file descriptor for " << path << "\n";
+        return;
+    }
+    if (err || bytesRead == 0)
+    {
+        if (readingStateGood())
+        {
+            std::cerr << name << " read failed\n";
+        }
+        restartRead();
+        return;
+    }
+
+    // null terminate the string so we don't walk off the end
+    std::array<char, 128>& bufferRef = *buffer;
+    bufferRef[bytesRead] = '\0';
+
+    try
+    {
+        rawValue = std::stod(bufferRef.data());
+        updateValue((rawValue / sensorFactor) + sensorOffset);
+    }
+    catch (const std::invalid_argument&)
+    {
+        std::cerr << "Could not parse  input from " << path << "\n";
+        incrementError();
+    }
+
+    restartRead();
+}
+
+void PSUSensor::checkThresholds()
+{
+    if (!readingStateGood())
+    {
+        return;
+    }
+
+    thresholds::checkThresholdsPowerDelay(weak_from_this(), thresholdTimer);
+}
diff --git a/src/psu/PSUSensor.hpp b/src/psu/PSUSensor.hpp
new file mode 100644
index 0000000..09601f8
--- /dev/null
+++ b/src/psu/PSUSensor.hpp
@@ -0,0 +1,82 @@
+#pragma once
+
+#include "DeviceMgmt.hpp"
+#include "PwmSensor.hpp"
+#include "Thresholds.hpp"
+#include "sensor.hpp"
+
+#include <boost/asio/random_access_file.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+
+#include <array>
+#include <memory>
+#include <string>
+#include <utility>
+
+class PSUSensor : public Sensor, public std::enable_shared_from_this<PSUSensor>
+{
+  public:
+    PSUSensor(const std::string& path, const std::string& objectType,
+              sdbusplus::asio::object_server& objectServer,
+              std::shared_ptr<sdbusplus::asio::connection>& conn,
+              boost::asio::io_context& io, const std::string& sensorName,
+              std::vector<thresholds::Threshold>&& thresholds,
+              const std::string& sensorConfiguration,
+              const PowerState& powerState, const std::string& sensorUnits,
+              unsigned int factor, double max, double min, double offset,
+              const std::string& label, size_t tSize, double pollRate,
+              const std::shared_ptr<I2CDevice>& i2cDevice);
+    ~PSUSensor() override;
+    void setupRead();
+    void activate(const std::string& newPath,
+                  const std::shared_ptr<I2CDevice>& newI2CDevice);
+    void deactivate();
+    bool isActive();
+
+    std::shared_ptr<I2CDevice> getI2CDevice() const
+    {
+        return i2cDevice;
+    }
+
+  private:
+    // Note, this buffer is a shared_ptr because during a read, its lifetime
+    // might have to outlive the PSUSensor class if the object gets destroyed
+    // while in the middle of a read operation
+    std::shared_ptr<std::array<char, 128>> buffer;
+    std::shared_ptr<I2CDevice> i2cDevice;
+    sdbusplus::asio::object_server& objServer;
+    boost::asio::random_access_file inputDev;
+    boost::asio::steady_timer waitTimer;
+    std::string path;
+    unsigned int sensorFactor;
+    double sensorOffset;
+    thresholds::ThresholdTimer thresholdTimer;
+    void restartRead();
+    void handleResponse(const boost::system::error_code& err, size_t bytesRead);
+    void checkThresholds() override;
+    unsigned int sensorPollMs = defaultSensorPollMs;
+
+    static constexpr size_t warnAfterErrorCount = 10;
+
+  public:
+    static constexpr double defaultSensorPoll = 1.0;
+    static constexpr unsigned int defaultSensorPollMs =
+        static_cast<unsigned int>(defaultSensorPoll * 1000);
+};
+
+class PSUProperty
+{
+  public:
+    PSUProperty(std::string name, double max, double min, unsigned int factor,
+                double offset) :
+        labelTypeName(std::move(name)), maxReading(max), minReading(min),
+        sensorScaleFactor(factor), sensorOffset(offset)
+    {}
+    ~PSUProperty() = default;
+
+    std::string labelTypeName;
+    double maxReading;
+    double minReading;
+    unsigned int sensorScaleFactor;
+    double sensorOffset;
+};
diff --git a/src/psu/PSUSensorMain.cpp b/src/psu/PSUSensorMain.cpp
new file mode 100644
index 0000000..3f9997c
--- /dev/null
+++ b/src/psu/PSUSensorMain.cpp
@@ -0,0 +1,1272 @@
+/*
+// 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 "DeviceMgmt.hpp"
+#include "PSUEvent.hpp"
+#include "PSUSensor.hpp"
+#include "PwmSensor.hpp"
+#include "SensorPaths.hpp"
+#include "Thresholds.hpp"
+#include "Utils.hpp"
+#include "VariantVisitors.hpp"
+
+#include <boost/algorithm/string/case_conv.hpp>
+#include <boost/algorithm/string/replace.hpp>
+#include <boost/asio/error.hpp>
+#include <boost/asio/io_context.hpp>
+#include <boost/asio/post.hpp>
+#include <boost/asio/steady_timer.hpp>
+#include <boost/container/flat_map.hpp>
+#include <boost/container/flat_set.hpp>
+#include <sdbusplus/asio/connection.hpp>
+#include <sdbusplus/asio/object_server.hpp>
+#include <sdbusplus/bus.hpp>
+#include <sdbusplus/bus/match.hpp>
+#include <sdbusplus/exception.hpp>
+#include <sdbusplus/message.hpp>
+#include <sdbusplus/message/native_types.hpp>
+
+#include <algorithm>
+#include <array>
+#include <cctype>
+#include <chrono>
+#include <cmath>
+#include <cstddef>
+#include <cstdint>
+#include <exception>
+#include <filesystem>
+#include <fstream>
+#include <functional>
+#include <iostream>
+#include <memory>
+#include <regex>
+#include <stdexcept>
+#include <string>
+#include <string_view>
+#include <utility>
+#include <variant>
+#include <vector>
+
+static constexpr bool debug = false;
+static std::regex i2cDevRegex(R"((\/i2c\-\d+\/\d+-[a-fA-F0-9]{4,4})(\/|$))");
+
+static const I2CDeviceTypeMap sensorTypes{
+    {"ADC128D818", I2CDeviceType{"adc128d818", true}},
+    {"ADM1266", I2CDeviceType{"adm1266", true}},
+    {"ADM1272", I2CDeviceType{"adm1272", true}},
+    {"ADM1275", I2CDeviceType{"adm1275", true}},
+    {"ADM1278", I2CDeviceType{"adm1278", true}},
+    {"ADM1293", I2CDeviceType{"adm1293", true}},
+    {"ADS1015", I2CDeviceType{"ads1015", true}},
+    {"ADS7830", I2CDeviceType{"ads7830", true}},
+    {"AHE50DC_FAN", I2CDeviceType{"ahe50dc_fan", true}},
+    {"BMR490", I2CDeviceType{"bmr490", true}},
+    {"cffps", I2CDeviceType{"cffps", true}},
+    {"cffps1", I2CDeviceType{"cffps", true}},
+    {"cffps2", I2CDeviceType{"cffps", true}},
+    {"cffps3", I2CDeviceType{"cffps", true}},
+    {"DPS800", I2CDeviceType{"dps800", true}},
+    {"INA219", I2CDeviceType{"ina219", true}},
+    {"INA230", I2CDeviceType{"ina230", true}},
+    {"INA238", I2CDeviceType{"ina238", true}},
+    {"IPSPS1", I2CDeviceType{"ipsps1", true}},
+    {"IR38060", I2CDeviceType{"ir38060", true}},
+    {"IR38164", I2CDeviceType{"ir38164", true}},
+    {"IR38263", I2CDeviceType{"ir38263", true}},
+    {"ISL28022", I2CDeviceType{"isl28022", true}},
+    {"ISL68137", I2CDeviceType{"isl68137", true}},
+    {"ISL68220", I2CDeviceType{"isl68220", true}},
+    {"ISL68223", I2CDeviceType{"isl68223", true}},
+    {"ISL69225", I2CDeviceType{"isl69225", true}},
+    {"ISL69243", I2CDeviceType{"isl69243", true}},
+    {"ISL69260", I2CDeviceType{"isl69260", true}},
+    {"LM25066", I2CDeviceType{"lm25066", true}},
+    {"LTC2945", I2CDeviceType{"ltc2945", true}},
+    {"LTC4286", I2CDeviceType{"ltc4286", true}},
+    {"LTC4287", I2CDeviceType{"ltc4287", true}},
+    {"MAX5970", I2CDeviceType{"max5970", true}},
+    {"MAX11607", I2CDeviceType{"max11607", false}},
+    {"MAX11615", I2CDeviceType{"max11615", false}},
+    {"MAX11617", I2CDeviceType{"max11617", false}},
+    {"MAX16601", I2CDeviceType{"max16601", true}},
+    {"MAX20710", I2CDeviceType{"max20710", true}},
+    {"MAX20730", I2CDeviceType{"max20730", true}},
+    {"MAX20734", I2CDeviceType{"max20734", true}},
+    {"MAX20796", I2CDeviceType{"max20796", true}},
+    {"MAX34451", I2CDeviceType{"max34451", true}},
+    {"MP2856", I2CDeviceType{"mp2856", true}},
+    {"MP2857", I2CDeviceType{"mp2857", true}},
+    {"MP2971", I2CDeviceType{"mp2971", true}},
+    {"MP2973", I2CDeviceType{"mp2973", true}},
+    {"MP2975", I2CDeviceType{"mp2975", true}},
+    {"MP5023", I2CDeviceType{"mp5023", true}},
+    {"MP5990", I2CDeviceType{"mp5990", true}},
+    {"MPQ8785", I2CDeviceType{"mpq8785", true}},
+    {"NCP4200", I2CDeviceType{"ncp4200", true}},
+    {"PLI1209BC", I2CDeviceType{"pli1209bc", true}},
+    {"pmbus", I2CDeviceType{"pmbus", true}},
+    {"PXE1610", I2CDeviceType{"pxe1610", true}},
+    {"RAA228000", I2CDeviceType{"raa228000", true}},
+    {"RAA228004", I2CDeviceType{"raa228004", true}},
+    {"RAA228228", I2CDeviceType{"raa228228", true}},
+    {"RAA228620", I2CDeviceType{"raa228620", true}},
+    {"RAA229001", I2CDeviceType{"raa229001", true}},
+    {"RAA229004", I2CDeviceType{"raa229004", true}},
+    {"RAA229126", I2CDeviceType{"raa229126", true}},
+    {"RTQ6056", I2CDeviceType{"rtq6056", false}},
+    {"SBRMI", I2CDeviceType{"sbrmi", true}},
+    {"smpro_hwmon", I2CDeviceType{"smpro", false}},
+    {"TDA38640", I2CDeviceType{"tda38640", true}},
+    {"TPS53679", I2CDeviceType{"tps53679", true}},
+    {"TPS546D24", I2CDeviceType{"tps546d24", true}},
+    {"XDP710", I2CDeviceType{"xdp710", true}},
+    {"XDPE11280", I2CDeviceType{"xdpe11280", true}},
+    {"XDPE12284", I2CDeviceType{"xdpe12284", true}},
+    {"XDPE152C4", I2CDeviceType{"xdpe152c4", true}},
+};
+
+enum class DevTypes
+{
+    Unknown = 0,
+    HWMON,
+    IIO
+};
+
+struct DevParams
+{
+    unsigned int matchIndex = 0;
+    std::string matchRegEx;
+    std::string nameRegEx;
+};
+
+namespace fs = std::filesystem;
+
+static boost::container::flat_map<std::string, std::shared_ptr<PSUSensor>>
+    sensors;
+static boost::container::flat_map<std::string, std::unique_ptr<PSUCombineEvent>>
+    combineEvents;
+static boost::container::flat_map<std::string, std::unique_ptr<PwmSensor>>
+    pwmSensors;
+static boost::container::flat_map<std::string, std::string> sensorTable;
+static boost::container::flat_map<std::string, PSUProperty> labelMatch;
+static EventPathList eventMatch;
+static EventPathList limitEventMatch;
+
+static boost::container::flat_map<size_t, bool> cpuPresence;
+static boost::container::flat_map<DevTypes, DevParams> devParamMap;
+
+// Function CheckEvent will check each attribute from eventMatch table in the
+// sysfs. If the attributes exists in sysfs, then store the complete path
+// of the attribute into eventPathList.
+void checkEvent(const std::string& directory, const EventPathList& eventMatch,
+                EventPathList& eventPathList)
+{
+    for (const auto& match : eventMatch)
+    {
+        const std::vector<std::string>& eventAttrs = match.second;
+        const std::string& eventName = match.first;
+        for (const auto& eventAttr : eventAttrs)
+        {
+            std::string eventPath = directory;
+            eventPath += "/";
+            eventPath += eventAttr;
+
+            std::ifstream eventFile(eventPath);
+            if (!eventFile.good())
+            {
+                continue;
+            }
+
+            eventPathList[eventName].push_back(eventPath);
+        }
+    }
+}
+
+// Check Group Events which contains more than one targets in each combine
+// events.
+void checkGroupEvent(const std::string& directory,
+                     GroupEventPathList& groupEventPathList)
+{
+    EventPathList pathList;
+    std::vector<fs::path> eventPaths;
+    if (!findFiles(fs::path(directory), R"(fan\d+_(alarm|fault))", eventPaths))
+    {
+        return;
+    }
+
+    for (const auto& eventPath : eventPaths)
+    {
+        std::string attrName = eventPath.filename();
+        pathList[attrName.substr(0, attrName.find('_'))].push_back(eventPath);
+    }
+    groupEventPathList["FanFault"] = pathList;
+}
+
+// Function checkEventLimits will check all the psu related xxx_input attributes
+// in sysfs to see if xxx_crit_alarm xxx_lcrit_alarm xxx_max_alarm
+// xxx_min_alarm exist, then store the existing paths of the alarm attributes
+// to eventPathList.
+void checkEventLimits(const std::string& sensorPathStr,
+                      const EventPathList& limitEventMatch,
+                      EventPathList& eventPathList)
+{
+    auto attributePartPos = sensorPathStr.find_last_of('_');
+    if (attributePartPos == std::string::npos)
+    {
+        // There is no '_' in the string, skip it
+        return;
+    }
+    auto attributePart =
+        std::string_view(sensorPathStr).substr(attributePartPos + 1);
+    if (attributePart != "input")
+    {
+        // If the sensor is not xxx_input, skip it
+        return;
+    }
+
+    auto prefixPart = sensorPathStr.substr(0, attributePartPos + 1);
+    for (const auto& limitMatch : limitEventMatch)
+    {
+        const std::vector<std::string>& limitEventAttrs = limitMatch.second;
+        const std::string& eventName = limitMatch.first;
+        for (const auto& limitEventAttr : limitEventAttrs)
+        {
+            auto limitEventPath = prefixPart + limitEventAttr;
+            std::ifstream eventFile(limitEventPath);
+            if (!eventFile.good())
+            {
+                continue;
+            }
+            eventPathList[eventName].push_back(limitEventPath);
+        }
+    }
+}
+
+static void checkPWMSensor(
+    const fs::path& sensorPath, std::string& labelHead,
+    const std::string& interfacePath,
+    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
+    sdbusplus::asio::object_server& objectServer, const std::string& psuName)
+{
+    if (!labelHead.starts_with("fan"))
+    {
+        return;
+    }
+    std::string labelHeadIndex = labelHead.substr(3);
+
+    const std::string& sensorPathStr = sensorPath.string();
+    const std::string& pwmPathStr =
+        boost::replace_all_copy(sensorPathStr, "input", "target");
+    std::ifstream pwmFile(pwmPathStr);
+    if (!pwmFile.good())
+    {
+        return;
+    }
+
+    auto findPWMSensor = pwmSensors.find(psuName + labelHead);
+    if (findPWMSensor != pwmSensors.end())
+    {
+        return;
+    }
+
+    std::string name = "Pwm_";
+    name += psuName;
+    name += "_Fan_";
+    name += labelHeadIndex;
+
+    std::string objPath = interfacePath;
+    objPath += "_Fan_";
+    objPath += labelHeadIndex;
+
+    pwmSensors[psuName + labelHead] = std::make_unique<PwmSensor>(
+        name, pwmPathStr, dbusConnection, objectServer, objPath, "PSU");
+}
+
+static void createSensorsCallback(
+    boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
+    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
+    const ManagedObjectType& sensorConfigs,
+    const std::shared_ptr<boost::container::flat_set<std::string>>&
+        sensorsChanged,
+    bool activateOnly)
+{
+    int numCreated = 0;
+    bool firstScan = sensorsChanged == nullptr;
+
+    auto devices = instantiateDevices(sensorConfigs, sensors, sensorTypes);
+
+    std::vector<fs::path> pmbusPaths;
+    findFiles(fs::path("/sys/bus/iio/devices"), "name", pmbusPaths);
+    findFiles(fs::path("/sys/class/hwmon"), "name", pmbusPaths);
+    if (pmbusPaths.empty())
+    {
+        std::cerr << "No PSU sensors in system\n";
+        return;
+    }
+
+    boost::container::flat_set<std::string> directories;
+    for (const auto& pmbusPath : pmbusPaths)
+    {
+        EventPathList eventPathList;
+        GroupEventPathList groupEventPathList;
+
+        std::ifstream nameFile(pmbusPath);
+        if (!nameFile.good())
+        {
+            std::cerr << "Failure finding pmbus path " << pmbusPath << "\n";
+            continue;
+        }
+
+        std::string pmbusName;
+        std::getline(nameFile, pmbusName);
+        nameFile.close();
+
+        if (sensorTypes.find(pmbusName) == sensorTypes.end())
+        {
+            // To avoid this error message, add your driver name to
+            // the pmbusNames vector at the top of this file.
+            std::cerr << "Driver name " << pmbusName
+                      << " not found in sensor whitelist\n";
+            continue;
+        }
+
+        auto directory = pmbusPath.parent_path();
+
+        auto ret = directories.insert(directory.string());
+        if (!ret.second)
+        {
+            std::cerr << "Duplicate path " << directory.string() << "\n";
+            continue; // check if path has already been searched
+        }
+
+        DevTypes devType = DevTypes::HWMON;
+        std::string deviceName;
+        if (directory.parent_path() == "/sys/class/hwmon")
+        {
+            std::string devicePath = fs::canonical(directory / "device");
+            std::smatch match;
+            // Find /i2c-<bus>/<bus>-<address> match in device path
+            std::regex_search(devicePath, match, i2cDevRegex);
+            if (match.empty())
+            {
+                std::cerr << "Found bad device path " << devicePath << "\n";
+                continue;
+            }
+            // Extract <bus>-<address>
+            std::string matchStr = match[1];
+            deviceName = matchStr.substr(matchStr.find_last_of('/') + 1);
+        }
+        else
+        {
+            deviceName = fs::canonical(directory).parent_path().stem();
+            devType = DevTypes::IIO;
+        }
+
+        size_t bus = 0;
+        size_t addr = 0;
+        if (!getDeviceBusAddr(deviceName, bus, addr))
+        {
+            continue;
+        }
+
+        const SensorBaseConfigMap* baseConfig = nullptr;
+        const SensorData* sensorData = nullptr;
+        const std::string* interfacePath = nullptr;
+        std::string sensorType;
+        size_t thresholdConfSize = 0;
+
+        for (const auto& [path, cfgData] : sensorConfigs)
+        {
+            sensorData = &cfgData;
+            for (const auto& [type, dt] : sensorTypes)
+            {
+                auto sensorBase = sensorData->find(configInterfaceName(type));
+                if (sensorBase != sensorData->end())
+                {
+                    baseConfig = &sensorBase->second;
+                    sensorType = type;
+                    break;
+                }
+            }
+            if (baseConfig == nullptr)
+            {
+                std::cerr << "error finding base configuration for "
+                          << deviceName << "\n";
+                continue;
+            }
+
+            auto configBus = baseConfig->find("Bus");
+            auto configAddress = baseConfig->find("Address");
+
+            if (configBus == baseConfig->end() ||
+                configAddress == baseConfig->end())
+            {
+                std::cerr << "error finding necessary entry in configuration\n";
+                continue;
+            }
+
+            const uint64_t* confBus =
+                std::get_if<uint64_t>(&(configBus->second));
+            const uint64_t* confAddr =
+                std::get_if<uint64_t>(&(configAddress->second));
+            if (confBus == nullptr || confAddr == nullptr)
+            {
+                std::cerr
+                    << "Cannot get bus or address, invalid configuration\n";
+                continue;
+            }
+
+            if ((*confBus != bus) || (*confAddr != addr))
+            {
+                if constexpr (debug)
+                {
+                    std::cerr << "Configuration skipping " << *confBus << "-"
+                              << *confAddr << " because not " << bus << "-"
+                              << addr << "\n";
+                }
+                continue;
+            }
+
+            std::vector<thresholds::Threshold> confThresholds;
+            if (!parseThresholdsFromConfig(*sensorData, confThresholds))
+            {
+                std::cerr << "error populating total thresholds\n";
+            }
+            thresholdConfSize = confThresholds.size();
+
+            interfacePath = &path.str;
+            break;
+        }
+        if (interfacePath == nullptr)
+        {
+            // To avoid this error message, add your export map entry,
+            // from Entity Manager, to sensorTypes at the top of this file.
+            std::cerr << "failed to find match for " << deviceName << "\n";
+            continue;
+        }
+
+        auto findI2CDev = devices.find(*interfacePath);
+
+        std::shared_ptr<I2CDevice> i2cDev;
+        if (findI2CDev != devices.end())
+        {
+            if (activateOnly && !findI2CDev->second.second)
+            {
+                continue;
+            }
+            i2cDev = findI2CDev->second.first;
+        }
+
+        auto findPSUName = baseConfig->find("Name");
+        if (findPSUName == baseConfig->end())
+        {
+            std::cerr << "could not determine configuration name for "
+                      << deviceName << "\n";
+            continue;
+        }
+        const std::string* psuName =
+            std::get_if<std::string>(&(findPSUName->second));
+        if (psuName == nullptr)
+        {
+            std::cerr << "Cannot find psu name, invalid configuration\n";
+            continue;
+        }
+
+        auto findCPU = baseConfig->find("CPURequired");
+        if (findCPU != baseConfig->end())
+        {
+            size_t index = std::visit(VariantToIntVisitor(), findCPU->second);
+            auto presenceFind = cpuPresence.find(index);
+            if (presenceFind == cpuPresence.end() || !presenceFind->second)
+            {
+                continue;
+            }
+        }
+
+        // on rescans, only update sensors we were signaled by
+        if (!firstScan)
+        {
+            std::string psuNameStr = "/" + escapeName(*psuName);
+            auto it =
+                std::find_if(sensorsChanged->begin(), sensorsChanged->end(),
+                             [psuNameStr](std::string& s) {
+                                 return s.ends_with(psuNameStr);
+                             });
+
+            if (it == sensorsChanged->end())
+            {
+                continue;
+            }
+            sensorsChanged->erase(it);
+        }
+        checkEvent(directory.string(), eventMatch, eventPathList);
+        checkGroupEvent(directory.string(), groupEventPathList);
+
+        PowerState readState = getPowerState(*baseConfig);
+
+        /* Check if there are more sensors in the same interface */
+        int i = 1;
+        std::vector<std::string> psuNames;
+        do
+        {
+            // Individual string fields: Name, Name1, Name2, Name3, ...
+            psuNames.push_back(
+                escapeName(std::get<std::string>(findPSUName->second)));
+            findPSUName = baseConfig->find("Name" + std::to_string(i++));
+        } while (findPSUName != baseConfig->end());
+
+        std::vector<fs::path> sensorPaths;
+        if (!findFiles(directory, devParamMap[devType].matchRegEx, sensorPaths,
+                       0))
+        {
+            std::cerr << "No PSU non-label sensor in PSU\n";
+            continue;
+        }
+
+        /* read max value in sysfs for in, curr, power, temp, ... */
+        if (!findFiles(directory, R"(\w\d+_max$)", sensorPaths, 0))
+        {
+            if constexpr (debug)
+            {
+                std::cerr << "No max name in PSU \n";
+            }
+        }
+
+        float pollRate = getPollRate(*baseConfig, PSUSensor::defaultSensorPoll);
+
+        /* Find array of labels to be exposed if it is defined in config */
+        std::vector<std::string> findLabels;
+        auto findLabelObj = baseConfig->find("Labels");
+        if (findLabelObj != baseConfig->end())
+        {
+            findLabels =
+                std::get<std::vector<std::string>>(findLabelObj->second);
+        }
+
+        std::regex sensorNameRegEx(devParamMap[devType].nameRegEx);
+        std::smatch matches;
+
+        for (const auto& sensorPath : sensorPaths)
+        {
+            bool maxLabel = false;
+            std::string labelHead;
+            std::string sensorPathStr = sensorPath.string();
+            std::string sensorNameStr = sensorPath.filename();
+            std::string sensorNameSubStr;
+            if (std::regex_search(sensorNameStr, matches, sensorNameRegEx))
+            {
+                // hwmon *_input filename without number:
+                // in, curr, power, temp, ...
+                // iio in_*_raw filename without number:
+                // voltage, temp, pressure, ...
+                sensorNameSubStr = matches[devParamMap[devType].matchIndex];
+            }
+            else
+            {
+                std::cerr << "Could not extract the alpha prefix from "
+                          << sensorNameStr;
+                continue;
+            }
+
+            std::string labelPath;
+
+            if (devType == DevTypes::HWMON)
+            {
+                /* find and differentiate _max and _input to replace "label" */
+                size_t pos = sensorPathStr.find('_');
+                if (pos != std::string::npos)
+                {
+                    std::string sensorPathStrMax = sensorPathStr.substr(pos);
+                    if (sensorPathStrMax == "_max")
+                    {
+                        labelPath = boost::replace_all_copy(sensorPathStr,
+                                                            "max", "label");
+                        maxLabel = true;
+                    }
+                    else
+                    {
+                        labelPath = boost::replace_all_copy(sensorPathStr,
+                                                            "input", "label");
+                        maxLabel = false;
+                    }
+                }
+                else
+                {
+                    continue;
+                }
+
+                std::ifstream labelFile(labelPath);
+                if (!labelFile.good())
+                {
+                    if constexpr (debug)
+                    {
+                        std::cerr << "Input file " << sensorPath
+                                  << " has no corresponding label file\n";
+                    }
+                    // hwmon *_input filename with number:
+                    // temp1, temp2, temp3, ...
+                    labelHead =
+                        sensorNameStr.substr(0, sensorNameStr.find('_'));
+                }
+                else
+                {
+                    std::string label;
+                    std::getline(labelFile, label);
+                    labelFile.close();
+                    auto findSensor = sensors.find(label);
+                    if (findSensor != sensors.end())
+                    {
+                        continue;
+                    }
+
+                    // hwmon corresponding *_label file contents:
+                    // vin1, vout1, ...
+                    labelHead = label.substr(0, label.find(' '));
+                }
+
+                /* append "max" for labelMatch */
+                if (maxLabel)
+                {
+                    labelHead.insert(0, "max");
+                }
+
+                checkPWMSensor(sensorPath, labelHead, *interfacePath,
+                               dbusConnection, objectServer, psuNames[0]);
+            }
+            else if (devType == DevTypes::IIO)
+            {
+                auto findIIOHyphen = sensorNameStr.find_last_of('_');
+                labelHead = sensorNameStr.substr(0, findIIOHyphen);
+            }
+
+            if constexpr (debug)
+            {
+                std::cerr << "Sensor type=\"" << sensorNameSubStr
+                          << "\" label=\"" << labelHead << "\"\n";
+            }
+
+            if (!findLabels.empty())
+            {
+                /* Check if this labelHead is enabled in config file */
+                if (std::find(findLabels.begin(), findLabels.end(),
+                              labelHead) == findLabels.end())
+                {
+                    if constexpr (debug)
+                    {
+                        std::cerr << "could not find " << labelHead
+                                  << " in the Labels list\n";
+                    }
+                    continue;
+                }
+            }
+
+            auto findProperty = labelMatch.find(sensorNameSubStr);
+            if (findProperty == labelMatch.end())
+            {
+                if constexpr (debug)
+                {
+                    std::cerr << "Could not find matching default property for "
+                              << sensorNameSubStr << "\n";
+                }
+                continue;
+            }
+
+            // Protect the hardcoded labelMatch list from changes,
+            // by making a copy and modifying that instead.
+            // Avoid bleedthrough of one device's customizations to
+            // the next device, as each should be independently customizable.
+            PSUProperty psuProperty = findProperty->second;
+
+            // Use label head as prefix for reading from config file,
+            // example if temp1: temp1_Name, temp1_Scale, temp1_Min, ...
+            std::string keyName = labelHead + "_Name";
+            std::string keyScale = labelHead + "_Scale";
+            std::string keyMin = labelHead + "_Min";
+            std::string keyMax = labelHead + "_Max";
+            std::string keyOffset = labelHead + "_Offset";
+            std::string keyPowerState = labelHead + "_PowerState";
+
+            bool customizedName = false;
+            auto findCustomName = baseConfig->find(keyName);
+            if (findCustomName != baseConfig->end())
+            {
+                try
+                {
+                    psuProperty.labelTypeName = std::visit(
+                        VariantToStringVisitor(), findCustomName->second);
+                }
+                catch (const std::invalid_argument&)
+                {
+                    std::cerr << "Unable to parse " << keyName << "\n";
+                    continue;
+                }
+
+                // All strings are valid, including empty string
+                customizedName = true;
+            }
+
+            bool customizedScale = false;
+            auto findCustomScale = baseConfig->find(keyScale);
+            if (findCustomScale != baseConfig->end())
+            {
+                try
+                {
+                    psuProperty.sensorScaleFactor = std::visit(
+                        VariantToUnsignedIntVisitor(), findCustomScale->second);
+                }
+                catch (const std::invalid_argument&)
+                {
+                    std::cerr << "Unable to parse " << keyScale << "\n";
+                    continue;
+                }
+
+                // Avoid later division by zero
+                if (psuProperty.sensorScaleFactor > 0)
+                {
+                    customizedScale = true;
+                }
+                else
+                {
+                    std::cerr << "Unable to accept " << keyScale << "\n";
+                    continue;
+                }
+            }
+
+            auto findCustomMin = baseConfig->find(keyMin);
+            if (findCustomMin != baseConfig->end())
+            {
+                try
+                {
+                    psuProperty.minReading = std::visit(
+                        VariantToDoubleVisitor(), findCustomMin->second);
+                }
+                catch (const std::invalid_argument&)
+                {
+                    std::cerr << "Unable to parse " << keyMin << "\n";
+                    continue;
+                }
+            }
+
+            auto findCustomMax = baseConfig->find(keyMax);
+            if (findCustomMax != baseConfig->end())
+            {
+                try
+                {
+                    psuProperty.maxReading = std::visit(
+                        VariantToDoubleVisitor(), findCustomMax->second);
+                }
+                catch (const std::invalid_argument&)
+                {
+                    std::cerr << "Unable to parse " << keyMax << "\n";
+                    continue;
+                }
+            }
+
+            auto findCustomOffset = baseConfig->find(keyOffset);
+            if (findCustomOffset != baseConfig->end())
+            {
+                try
+                {
+                    psuProperty.sensorOffset = std::visit(
+                        VariantToDoubleVisitor(), findCustomOffset->second);
+                }
+                catch (const std::invalid_argument&)
+                {
+                    std::cerr << "Unable to parse " << keyOffset << "\n";
+                    continue;
+                }
+            }
+
+            // if we find label head power state set ，override the powerstate.
+            auto findPowerState = baseConfig->find(keyPowerState);
+            if (findPowerState != baseConfig->end())
+            {
+                std::string powerState = std::visit(VariantToStringVisitor(),
+                                                    findPowerState->second);
+                setReadState(powerState, readState);
+            }
+            if (!(psuProperty.minReading < psuProperty.maxReading))
+            {
+                std::cerr << "Min must be less than Max\n";
+                continue;
+            }
+
+            // If the sensor name is being customized by config file,
+            // then prefix/suffix composition becomes not necessary,
+            // and in fact not wanted, because it gets in the way.
+            std::string psuNameFromIndex;
+            std::string nameIndexStr = "1";
+            if (!customizedName)
+            {
+                /* Find out sensor name index for this label */
+                std::regex rgx("[A-Za-z]+([0-9]+)");
+                size_t nameIndex{0};
+                if (std::regex_search(labelHead, matches, rgx))
+                {
+                    nameIndexStr = matches[1];
+                    nameIndex = std::stoi(nameIndexStr);
+
+                    // Decrement to preserve alignment, because hwmon
+                    // human-readable filenames and labels use 1-based
+                    // numbering, but the "Name", "Name1", "Name2", etc. naming
+                    // convention (the psuNames vector) uses 0-based numbering.
+                    if (nameIndex > 0)
+                    {
+                        --nameIndex;
+                    }
+                }
+                else
+                {
+                    nameIndex = 0;
+                }
+
+                if (psuNames.size() <= nameIndex)
+                {
+                    std::cerr << "Could not pair " << labelHead
+                              << " with a Name field\n";
+                    continue;
+                }
+
+                psuNameFromIndex = psuNames[nameIndex];
+
+                if constexpr (debug)
+                {
+                    std::cerr << "Sensor label head " << labelHead
+                              << " paired with " << psuNameFromIndex
+                              << " at index " << nameIndex << "\n";
+                }
+            }
+
+            if (devType == DevTypes::HWMON)
+            {
+                checkEventLimits(sensorPathStr, limitEventMatch, eventPathList);
+            }
+
+            // Similarly, if sensor scaling factor is being customized,
+            // then the below power-of-10 constraint becomes unnecessary,
+            // as config should be able to specify an arbitrary divisor.
+            unsigned int factor = psuProperty.sensorScaleFactor;
+            if (!customizedScale)
+            {
+                // Preserve existing usage of hardcoded labelMatch table below
+                factor = std::pow(10.0, factor);
+
+                /* Change first char of substring to uppercase */
+                char firstChar =
+                    static_cast<char>(std::toupper(sensorNameSubStr[0]));
+                std::string strScaleFactor =
+                    firstChar + sensorNameSubStr.substr(1) + "ScaleFactor";
+
+                // Preserve existing configs by accepting earlier syntax,
+                // example CurrScaleFactor, PowerScaleFactor, ...
+                auto findScaleFactor = baseConfig->find(strScaleFactor);
+                if (findScaleFactor != baseConfig->end())
+                {
+                    factor = std::visit(VariantToIntVisitor(),
+                                        findScaleFactor->second);
+                }
+
+                if constexpr (debug)
+                {
+                    std::cerr << "Sensor scaling factor " << factor
+                              << " string " << strScaleFactor << "\n";
+                }
+            }
+
+            std::vector<thresholds::Threshold> sensorThresholds;
+            if (!parseThresholdsFromConfig(*sensorData, sensorThresholds,
+                                           &labelHead))
+            {
+                std::cerr << "error populating thresholds for "
+                          << sensorNameSubStr << "\n";
+            }
+
+            auto findSensorUnit = sensorTable.find(sensorNameSubStr);
+            if (findSensorUnit == sensorTable.end())
+            {
+                std::cerr << sensorNameSubStr
+                          << " is not a recognized sensor type\n";
+                continue;
+            }
+
+            if constexpr (debug)
+            {
+                std::cerr << "Sensor properties: Name \""
+                          << psuProperty.labelTypeName << "\" Scale "
+                          << psuProperty.sensorScaleFactor << " Min "
+                          << psuProperty.minReading << " Max "
+                          << psuProperty.maxReading << " Offset "
+                          << psuProperty.sensorOffset << "\n";
+            }
+
+            std::string sensorName = psuProperty.labelTypeName;
+            if (customizedName)
+            {
+                if (sensorName.empty())
+                {
+                    // Allow selective disabling of an individual sensor,
+                    // by customizing its name to an empty string.
+                    std::cerr << "Sensor disabled, empty string\n";
+                    continue;
+                }
+            }
+            else
+            {
+                // Sensor name not customized, do prefix/suffix composition,
+                // preserving default behavior by using psuNameFromIndex.
+                sensorName = psuNameFromIndex + " " + psuProperty.labelTypeName;
+
+                // The labelTypeName of a fan can be:
+                // "Fan Speed 1", "Fan Speed 2", "Fan Speed 3" ...
+                if (labelHead == "fan" + nameIndexStr)
+                {
+                    sensorName += nameIndexStr;
+                }
+            }
+
+            if constexpr (debug)
+            {
+                std::cerr << "Sensor name \"" << sensorName << "\" path \""
+                          << sensorPathStr << "\" type \"" << sensorType
+                          << "\"\n";
+            }
+            // destruct existing one first if already created
+
+            auto& sensor = sensors[sensorName];
+            if (!activateOnly)
+            {
+                sensor = nullptr;
+            }
+
+            if (sensor != nullptr)
+            {
+                sensor->activate(sensorPathStr, i2cDev);
+            }
+            else
+            {
+                sensors[sensorName] = std::make_shared<PSUSensor>(
+                    sensorPathStr, sensorType, objectServer, dbusConnection, io,
+                    sensorName, std::move(sensorThresholds), *interfacePath,
+                    readState, findSensorUnit->second, factor,
+                    psuProperty.maxReading, psuProperty.minReading,
+                    psuProperty.sensorOffset, labelHead, thresholdConfSize,
+                    pollRate, i2cDev);
+                sensors[sensorName]->setupRead();
+                ++numCreated;
+                if constexpr (debug)
+                {
+                    std::cerr
+                        << "Created " << numCreated << " sensors so far\n";
+                }
+            }
+        }
+
+        if (devType == DevTypes::HWMON)
+        {
+            // OperationalStatus event
+            combineEvents[*psuName + "OperationalStatus"] = nullptr;
+            combineEvents[*psuName + "OperationalStatus"] =
+                std::make_unique<PSUCombineEvent>(
+                    objectServer, dbusConnection, io, *psuName, readState,
+                    eventPathList, groupEventPathList, "OperationalStatus",
+                    pollRate);
+        }
+    }
+
+    if constexpr (debug)
+    {
+        std::cerr << "Created total of " << numCreated << " sensors\n";
+    }
+}
+
+static void
+    getPresentCpus(std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
+{
+    static const int depth = 2;
+    static const int numKeys = 1;
+    GetSubTreeType cpuSubTree;
+
+    try
+    {
+        auto getItems = dbusConnection->new_method_call(
+            mapper::busName, mapper::path, mapper::interface, mapper::subtree);
+        getItems.append(cpuInventoryPath, static_cast<int32_t>(depth),
+                        std::array<const char*, numKeys>{
+                            "xyz.openbmc_project.Inventory.Item"});
+        auto getItemsResp = dbusConnection->call(getItems);
+        getItemsResp.read(cpuSubTree);
+    }
+    catch (sdbusplus::exception_t& e)
+    {
+        std::cerr << "error getting inventory item subtree: " << e.what()
+                  << "\n";
+        return;
+    }
+
+    for (const auto& [path, objDict] : cpuSubTree)
+    {
+        auto obj = sdbusplus::message::object_path(path).filename();
+        boost::to_lower(obj);
+
+        if (!obj.starts_with("cpu") || objDict.empty())
+        {
+            continue;
+        }
+        const std::string& owner = objDict.begin()->first;
+
+        std::variant<bool> respValue;
+        try
+        {
+            auto getPresence = dbusConnection->new_method_call(
+                owner.c_str(), path.c_str(), "org.freedesktop.DBus.Properties",
+                "Get");
+            getPresence.append("xyz.openbmc_project.Inventory.Item", "Present");
+            auto resp = dbusConnection->call(getPresence);
+            resp.read(respValue);
+        }
+        catch (sdbusplus::exception_t& e)
+        {
+            std::cerr << "Error in getting CPU presence: " << e.what() << "\n";
+            continue;
+        }
+
+        auto* present = std::get_if<bool>(&respValue);
+        if (present != nullptr && *present)
+        {
+            int cpuIndex = 0;
+            try
+            {
+                cpuIndex = std::stoi(obj.substr(obj.size() - 1));
+            }
+            catch (const std::exception& e)
+            {
+                std::cerr << "Error converting CPU index, " << e.what() << '\n';
+                continue;
+            }
+            cpuPresence[cpuIndex] = *present;
+        }
+    }
+}
+
+void createSensors(
+    boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
+    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
+    const std::shared_ptr<boost::container::flat_set<std::string>>&
+        sensorsChanged,
+    bool activateOnly)
+{
+    auto getter = std::make_shared<GetSensorConfiguration>(
+        dbusConnection, [&io, &objectServer, &dbusConnection, sensorsChanged,
+                         activateOnly](const ManagedObjectType& sensorConfigs) {
+            createSensorsCallback(io, objectServer, dbusConnection,
+                                  sensorConfigs, sensorsChanged, activateOnly);
+        });
+    std::vector<std::string> types(sensorTypes.size());
+    for (const auto& [type, dt] : sensorTypes)
+    {
+        types.push_back(type);
+    }
+    getter->getConfiguration(types);
+}
+
+void propertyInitialize()
+{
+    sensorTable = {{"power", sensor_paths::unitWatts},
+                   {"curr", sensor_paths::unitAmperes},
+                   {"temp", sensor_paths::unitDegreesC},
+                   {"in", sensor_paths::unitVolts},
+                   {"voltage", sensor_paths::unitVolts},
+                   {"fan", sensor_paths::unitRPMs}};
+
+    labelMatch = {
+        {"pin", PSUProperty("Input Power", 3000, 0, 6, 0)},
+        {"pout", PSUProperty("Output Power", 3000, 0, 6, 0)},
+        {"power", PSUProperty("Output Power", 3000, 0, 6, 0)},
+        {"maxpin", PSUProperty("Max Input Power", 3000, 0, 6, 0)},
+        {"vin", PSUProperty("Input Voltage", 300, 0, 3, 0)},
+        {"maxvin", PSUProperty("Max Input Voltage", 300, 0, 3, 0)},
+        {"in_voltage", PSUProperty("Output Voltage", 255, 0, 3, 0)},
+        {"voltage", PSUProperty("Output Voltage", 255, 0, 3, 0)},
+        {"vout", PSUProperty("Output Voltage", 255, 0, 3, 0)},
+        {"vmon", PSUProperty("Auxiliary Input Voltage", 255, 0, 3, 0)},
+        {"in", PSUProperty("Output Voltage", 255, 0, 3, 0)},
+        {"iin", PSUProperty("Input Current", 20, 0, 3, 0)},
+        {"iout", PSUProperty("Output Current", 255, 0, 3, 0)},
+        {"curr", PSUProperty("Output Current", 255, 0, 3, 0)},
+        {"maxiout", PSUProperty("Max Output Current", 255, 0, 3, 0)},
+        {"temp", PSUProperty("Temperature", 127, -128, 3, 0)},
+        {"maxtemp", PSUProperty("Max Temperature", 127, -128, 3, 0)},
+        {"fan", PSUProperty("Fan Speed ", 30000, 0, 0, 0)}};
+
+    limitEventMatch = {{"PredictiveFailure", {"max_alarm", "min_alarm"}},
+                       {"Failure", {"crit_alarm", "lcrit_alarm"}}};
+
+    eventMatch = {{"PredictiveFailure", {"power1_alarm"}},
+                  {"Failure", {"in2_alarm"}},
+                  {"ACLost", {"in1_beep"}},
+                  {"ConfigureError", {"in1_fault"}}};
+
+    devParamMap = {
+        {DevTypes::HWMON, {1, R"(\w\d+_input$)", "([A-Za-z]+)[0-9]*_"}},
+        {DevTypes::IIO,
+         {2, R"(\w+_(raw|input)$)", "^(in|out)_([A-Za-z]+)[0-9]*_"}}};
+}
+
+static void powerStateChanged(
+    PowerState type, bool newState,
+    boost::container::flat_map<std::string, std::shared_ptr<PSUSensor>>&
+        sensors,
+    boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
+    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
+{
+    if (newState)
+    {
+        createSensors(io, objectServer, dbusConnection, nullptr, true);
+    }
+    else
+    {
+        for (auto& [path, sensor] : sensors)
+        {
+            if (sensor != nullptr && sensor->readState == type)
+            {
+                sensor->deactivate();
+            }
+        }
+    }
+}
+
+int main()
+{
+    boost::asio::io_context io;
+    auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
+
+    sdbusplus::asio::object_server objectServer(systemBus, true);
+    objectServer.add_manager("/xyz/openbmc_project/sensors");
+    objectServer.add_manager("/xyz/openbmc_project/control");
+    systemBus->request_name("xyz.openbmc_project.PSUSensor");
+    auto sensorsChanged =
+        std::make_shared<boost::container::flat_set<std::string>>();
+
+    propertyInitialize();
+
+    auto powerCallBack = [&io, &objectServer,
+                          &systemBus](PowerState type, bool state) {
+        powerStateChanged(type, state, sensors, io, objectServer, systemBus);
+    };
+
+    setupPowerMatchCallback(systemBus, powerCallBack);
+
+    boost::asio::post(io, [&]() {
+        createSensors(io, objectServer, systemBus, nullptr, false);
+    });
+    boost::asio::steady_timer filterTimer(io);
+    std::function<void(sdbusplus::message_t&)> eventHandler =
+        [&](sdbusplus::message_t& message) {
+            if (message.is_method_error())
+            {
+                std::cerr << "callback method error\n";
+                return;
+            }
+            sensorsChanged->insert(message.get_path());
+            filterTimer.expires_after(std::chrono::seconds(3));
+            filterTimer.async_wait([&](const boost::system::error_code& ec) {
+                if (ec == boost::asio::error::operation_aborted)
+                {
+                    return;
+                }
+                if (ec)
+                {
+                    std::cerr << "timer error\n";
+                }
+                createSensors(io, objectServer, systemBus, sensorsChanged,
+                              false);
+            });
+        };
+
+    boost::asio::steady_timer cpuFilterTimer(io);
+    std::function<void(sdbusplus::message_t&)> cpuPresenceHandler =
+        [&](sdbusplus::message_t& message) {
+            std::string path = message.get_path();
+            boost::to_lower(path);
+
+            sdbusplus::message::object_path cpuPath(path);
+            std::string cpuName = cpuPath.filename();
+            if (!cpuName.starts_with("cpu"))
+            {
+                return;
+            }
+            size_t index = 0;
+            try
+            {
+                index = std::stoi(path.substr(path.size() - 1));
+            }
+            catch (const std::invalid_argument&)
+            {
+                std::cerr << "Found invalid path " << path << "\n";
+                return;
+            }
+
+            std::string objectName;
+            boost::container::flat_map<std::string, std::variant<bool>> values;
+            message.read(objectName, values);
+            auto findPresence = values.find("Present");
+            if (findPresence == values.end())
+            {
+                return;
+            }
+            try
+            {
+                cpuPresence[index] = std::get<bool>(findPresence->second);
+            }
+            catch (const std::bad_variant_access& err)
+            {
+                return;
+            }
+
+            if (!cpuPresence[index])
+            {
+                return;
+            }
+            cpuFilterTimer.expires_after(std::chrono::seconds(1));
+            cpuFilterTimer.async_wait([&](const boost::system::error_code& ec) {
+                if (ec == boost::asio::error::operation_aborted)
+                {
+                    return;
+                }
+                if (ec)
+                {
+                    std::cerr << "timer error\n";
+                    return;
+                }
+                createSensors(io, objectServer, systemBus, nullptr, false);
+            });
+        };
+
+    std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
+        setupPropertiesChangedMatches(*systemBus, sensorTypes, eventHandler);
+
+    matches.emplace_back(std::make_unique<sdbusplus::bus::match_t>(
+        static_cast<sdbusplus::bus_t&>(*systemBus),
+        "type='signal',member='PropertiesChanged',path_namespace='" +
+            std::string(cpuInventoryPath) +
+            "',arg0namespace='xyz.openbmc_project.Inventory.Item'",
+        cpuPresenceHandler));
+
+    getPresentCpus(systemBus);
+
+    setupManufacturingModeMatch(*systemBus);
+    io.run();
+}
diff --git a/src/psu/meson.build b/src/psu/meson.build
new file mode 100644
index 0000000..8f8df66
--- /dev/null
+++ b/src/psu/meson.build
@@ -0,0 +1,17 @@
+src_inc = include_directories('..')
+
+executable(
+    'psusensor',
+    'PSUEvent.cpp',
+    'PSUSensor.cpp',
+    'PSUSensorMain.cpp',
+    dependencies: [
+        default_deps,
+        devicemgmt_dep,
+        pwmsensor_dep,
+        thresholds_dep,
+        utils_dep,
+    ],
+    include_directories: src_inc,
+    install: true,
+)
\ No newline at end of file
