Support numeric effecters in dbus-to-host-effecter

Adds support of the numeric effecter PDR (section `28.11 Numeric
Effecter PDR` DSP0248 V1.3.0) type in dbus-to-host-effecter handler.
This handler will be applied for all PLDM termini but not only host.
The setting for one numeric effecter of one device can be:
{
    "mctp_eid": 20,
    "effecter_info": {
        "effecterPdrType": 9,
        "effecterID": 2,
        "entityType": 32903,
        "entityInstance": 2,
        "containerID": 2,
        "compositeEffecterCount": 1,
        "checkHostState": false
    },
    "effecters": [
        {
            "dbus_info": {
                "object_path": "/xyz/openbmc_project/sensors/power/A",
                "interface": "xyz.openbmc_project.Sensor.Value",
                "property_name": "Value",
                "property_type": "double"
            },
            "effecterDataSize": 5,
            "resolution": 1,
            "offset": 0,
            "unitModifier": 0
        }
    ]
}

Where:
+ effecterPdrType to difference state/numeric effecter type. Default
is state effecter.
+ effecterID should be effecter ID and should not empty.
+ checkHostState can be set to false to bypass checking host state.
+ effecterDataSize, resolution, offset, unitModifier are from numeric
effecter PDR (section `28.11 Numeric Effecter PDR` DSP0248 V1.3.0)

Signed-off-by: Thu Nguyen <thu@os.amperecomputing.com>
Change-Id: I438d7f204643edd4066e8a6ba28d53a97503fc4b
diff --git a/host-bmc/dbus_to_host_effecters.cpp b/host-bmc/dbus_to_host_effecters.cpp
deleted file mode 100644
index 9b1c250..0000000
--- a/host-bmc/dbus_to_host_effecters.cpp
+++ /dev/null
@@ -1,348 +0,0 @@
-#include "dbus_to_host_effecters.hpp"
-
-#include <libpldm/pdr.h>
-#include <libpldm/platform.h>
-
-#include <phosphor-logging/lg2.hpp>
-#include <xyz/openbmc_project/Common/error.hpp>
-#include <xyz/openbmc_project/State/Boot/Progress/client.hpp>
-#include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp>
-
-#include <fstream>
-
-PHOSPHOR_LOG2_USING;
-
-using namespace pldm::utils;
-
-namespace pldm
-{
-namespace host_effecters
-{
-using InternalFailure =
-    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
-
-constexpr auto hostEffecterJson = "dbus_to_host_effecter.json";
-
-void HostEffecterParser::populatePropVals(
-    const Json& dBusValues, std::vector<PropertyValue>& propertyValues,
-    const std::string& propertyType)
-
-{
-    for (const auto& elem : dBusValues)
-    {
-        auto value = jsonEntryToDbusVal(propertyType, elem);
-        propertyValues.emplace_back(value);
-    }
-}
-
-void HostEffecterParser::parseEffecterJson(const std::string& jsonPath)
-{
-    fs::path jsonDir(jsonPath);
-    if (!fs::exists(jsonDir) || fs::is_empty(jsonDir))
-    {
-        error("Effecter json file for remote terminus '{PATH}' does not exist.",
-              "PATH", jsonPath);
-        return;
-    }
-
-    fs::path jsonFilePath = jsonDir / hostEffecterJson;
-    if (!fs::exists(jsonFilePath))
-    {
-        error("Json at path '{PATH}' does not exist.", "PATH", jsonFilePath);
-        throw InternalFailure();
-    }
-
-    std::ifstream jsonFile(jsonFilePath);
-    auto data = Json::parse(jsonFile, nullptr, false);
-    if (data.is_discarded())
-    {
-        error("Failed to parse json file {PATH}", "PATH", jsonFilePath);
-        throw InternalFailure();
-    }
-    const Json empty{};
-    const std::vector<Json> emptyList{};
-
-    auto entries = data.value("entries", emptyList);
-    for (const auto& entry : entries)
-    {
-        EffecterInfo effecterInfo;
-        effecterInfo.mctpEid = entry.value("mctp_eid", 0xFF);
-        auto jsonEffecterInfo = entry.value("effecter_info", empty);
-        auto effecterId =
-            jsonEffecterInfo.value("effecterID", PLDM_INVALID_EFFECTER_ID);
-        effecterInfo.containerId = jsonEffecterInfo.value("containerID", 0);
-        effecterInfo.entityType = jsonEffecterInfo.value("entityType", 0);
-        effecterInfo.entityInstance =
-            jsonEffecterInfo.value("entityInstance", 0);
-        effecterInfo.compEffecterCnt =
-            jsonEffecterInfo.value("compositeEffecterCount", 0);
-        auto effecters = entry.value("effecters", emptyList);
-        for (const auto& effecter : effecters)
-        {
-            DBusEffecterMapping dbusInfo{};
-            auto jsonDbusInfo = effecter.value("dbus_info", empty);
-            dbusInfo.dbusMap.objectPath = jsonDbusInfo.value("object_path", "");
-            dbusInfo.dbusMap.interface = jsonDbusInfo.value("interface", "");
-            dbusInfo.dbusMap.propertyName =
-                jsonDbusInfo.value("property_name", "");
-            dbusInfo.dbusMap.propertyType =
-                jsonDbusInfo.value("property_type", "");
-            Json propertyValues = jsonDbusInfo["property_values"];
-
-            populatePropVals(propertyValues, dbusInfo.propertyValues,
-                             dbusInfo.dbusMap.propertyType);
-
-            const std::vector<uint8_t> emptyStates{};
-            auto state = effecter.value("state", empty);
-            dbusInfo.state.stateSetId = state.value("id", 0);
-            auto states = state.value("state_values", emptyStates);
-            if (dbusInfo.propertyValues.size() != states.size())
-            {
-                error(
-                    "Number of states do not match with number of D-Bus property values in the json. Object path at '{PATH}' and property '{PROPERTY}' will not be monitored",
-                    "PATH", dbusInfo.dbusMap.objectPath, "PROPERTY",
-                    dbusInfo.dbusMap.propertyName);
-                continue;
-            }
-            for (const auto& s : states)
-            {
-                dbusInfo.state.states.emplace_back(s);
-            }
-
-            auto effecterInfoIndex = hostEffecterInfo.size();
-            auto dbusInfoIndex = effecterInfo.dbusInfo.size();
-            createHostEffecterMatch(
-                dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface,
-                effecterInfoIndex, dbusInfoIndex, effecterId);
-            effecterInfo.dbusInfo.emplace_back(std::move(dbusInfo));
-        }
-        hostEffecterInfo.emplace_back(std::move(effecterInfo));
-    }
-}
-
-void HostEffecterParser::processHostEffecterChangeNotification(
-    const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex,
-    size_t dbusInfoIndex, uint16_t effecterId)
-{
-    using BootProgress =
-        sdbusplus::client::xyz::openbmc_project::state::boot::Progress<>;
-
-    const auto& propertyName = hostEffecterInfo[effecterInfoIndex]
-                                   .dbusInfo[dbusInfoIndex]
-                                   .dbusMap.propertyName;
-
-    const auto& it = chProperties.find(propertyName);
-
-    if (it == chProperties.end())
-    {
-        return;
-    }
-
-    if (effecterId == PLDM_INVALID_EFFECTER_ID)
-    {
-        constexpr auto localOrRemote = false;
-        effecterId = findStateEffecterId(
-            pdrRepo, hostEffecterInfo[effecterInfoIndex].entityType,
-            hostEffecterInfo[effecterInfoIndex].entityInstance,
-            hostEffecterInfo[effecterInfoIndex].containerId,
-            hostEffecterInfo[effecterInfoIndex]
-                .dbusInfo[dbusInfoIndex]
-                .state.stateSetId,
-            localOrRemote);
-        if (effecterId == PLDM_INVALID_EFFECTER_ID)
-        {
-            error(
-                "Effecter ID '{EFFECTERID}' of entity type '{TYPE}', entityInstance '{INSTANCE}' and containerID '{CONTAINER_ID}' not found in pdr repo",
-                "EFFECTERID", effecterId, "TYPE",
-                hostEffecterInfo[effecterInfoIndex].entityType, "INSTANCE",
-                hostEffecterInfo[effecterInfoIndex].entityInstance,
-                "CONTAINER_ID",
-                hostEffecterInfo[effecterInfoIndex].containerId);
-            return;
-        }
-    }
-    constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0";
-
-    try
-    {
-        auto propVal = dbusHandler->getDbusPropertyVariant(
-            hostStatePath, "BootProgress", BootProgress::interface);
-
-        using Stages = BootProgress::ProgressStages;
-        auto currHostState = sdbusplus::message::convert_from_string<Stages>(
-                                 std::get<std::string>(propVal))
-                                 .value();
-
-        if (currHostState != Stages::SystemInitComplete &&
-            currHostState != Stages::OSRunning &&
-            currHostState != Stages::SystemSetup)
-        {
-            info(
-                "Remote terminus is not up/active, current remote terminus state is: '{CURRENT_HOST_STATE}'",
-                "CURRENT_HOST_STATE", currHostState);
-            return;
-        }
-    }
-    catch (const sdbusplus::exception_t& e)
-    {
-        error(
-            "Error in getting current remote terminus state. Will still continue to set the remote terminus effecter, error - {ERROR}",
-            "ERROR", e);
-    }
-    uint8_t newState{};
-    try
-    {
-        newState =
-            findNewStateValue(effecterInfoIndex, dbusInfoIndex, it->second);
-    }
-    catch (const std::out_of_range& e)
-    {
-        error("Failed to find new state '{NEW_STATE}' in json, error - {ERROR}",
-              "ERROR", e, "NEW_STATE", newState);
-        return;
-    }
-
-    std::vector<set_effecter_state_field> stateField;
-    for (uint8_t i = 0; i < hostEffecterInfo[effecterInfoIndex].compEffecterCnt;
-         i++)
-    {
-        if (i == dbusInfoIndex)
-        {
-            stateField.push_back({PLDM_REQUEST_SET, newState});
-        }
-        else
-        {
-            stateField.push_back({PLDM_NO_CHANGE, 0});
-        }
-    }
-    int rc{};
-    try
-    {
-        rc = setHostStateEffecter(effecterInfoIndex, stateField, effecterId);
-    }
-    catch (const std::runtime_error& e)
-    {
-        error(
-            "Failed to set remote terminus state effecter for effecter ID '{EFFECTERID}', error - {ERROR}",
-            "ERROR", e, "EFFECTERID", effecterId);
-        return;
-    }
-    if (rc != PLDM_SUCCESS)
-    {
-        error(
-            "Failed to set the remote terminus state effecter for effecter ID '{EFFECTERID}', response code '{RC}'",
-            "EFFECTERID", effecterId, "RC", rc);
-    }
-}
-
-uint8_t HostEffecterParser::findNewStateValue(
-    size_t effecterInfoIndex, size_t dbusInfoIndex,
-    const PropertyValue& propertyValue)
-{
-    const auto& propValues = hostEffecterInfo[effecterInfoIndex]
-                                 .dbusInfo[dbusInfoIndex]
-                                 .propertyValues;
-    auto it = std::find(propValues.begin(), propValues.end(), propertyValue);
-    uint8_t newState{};
-    if (it != propValues.end())
-    {
-        auto index = std::distance(propValues.begin(), it);
-        newState = hostEffecterInfo[effecterInfoIndex]
-                       .dbusInfo[dbusInfoIndex]
-                       .state.states[index];
-    }
-    else
-    {
-        throw std::out_of_range("new state not found in json");
-    }
-    return newState;
-}
-
-int HostEffecterParser::setHostStateEffecter(
-    size_t effecterInfoIndex, std::vector<set_effecter_state_field>& stateField,
-    uint16_t effecterId)
-{
-    uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid;
-    uint8_t& compEffCnt = hostEffecterInfo[effecterInfoIndex].compEffecterCnt;
-    auto instanceId = instanceIdDb->next(mctpEid);
-
-    std::vector<uint8_t> requestMsg(
-        sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(compEffCnt) +
-            sizeof(set_effecter_state_field) * compEffCnt,
-        0);
-    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
-    auto rc = encode_set_state_effecter_states_req(
-        instanceId, effecterId, compEffCnt, stateField.data(), request);
-
-    if (rc != PLDM_SUCCESS)
-    {
-        error(
-            "Failed to encode set state effecter states message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with response code '{RC}'",
-            "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex,
-            rc);
-        instanceIdDb->free(mctpEid, instanceId);
-        return rc;
-    }
-
-    auto setStateEffecterStatesRespHandler = [](mctp_eid_t /*eid*/,
-                                                const pldm_msg* response,
-                                                size_t respMsgLen) {
-        if (response == nullptr || !respMsgLen)
-        {
-            error(
-                "Failed to receive response for setting state effecter states.");
-            return;
-        }
-        uint8_t completionCode{};
-        auto rc = decode_set_state_effecter_states_resp(response, respMsgLen,
-                                                        &completionCode);
-        if (rc)
-        {
-            error(
-                "Failed to decode response of set state effecter states, response code '{RC}'",
-                "RC", rc);
-            pldm::utils::reportError(
-                "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed");
-        }
-        if (completionCode)
-        {
-            error(
-                "Failed to set a remote terminus effecter, completion code '{CC}'",
-                "CC", completionCode);
-            pldm::utils::reportError(
-                "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed");
-        }
-    };
-
-    rc = handler->registerRequest(
-        mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES,
-        std::move(requestMsg), std::move(setStateEffecterStatesRespHandler));
-    if (rc)
-    {
-        error(
-            "Failed to send request to set an effecter on remote terminus for effecter ID '{EFFECTERID}', response code '{RC}'",
-            "EFFECTERID", effecterId, "RC", rc);
-    }
-    return rc;
-}
-
-void HostEffecterParser::createHostEffecterMatch(
-    const std::string& objectPath, const std::string& interface,
-    size_t effecterInfoIndex, size_t dbusInfoIndex, uint16_t effecterId)
-{
-    using namespace sdbusplus::bus::match::rules;
-    effecterInfoMatch.emplace_back(std::make_unique<sdbusplus::bus::match_t>(
-        pldm::utils::DBusHandler::getBus(),
-        propertiesChanged(objectPath, interface),
-        [this, effecterInfoIndex, dbusInfoIndex,
-         effecterId](sdbusplus::message_t& msg) {
-            DbusChgHostEffecterProps props;
-            std::string iface;
-            msg.read(iface, props);
-            processHostEffecterChangeNotification(props, effecterInfoIndex,
-                                                  dbusInfoIndex, effecterId);
-        }));
-}
-
-} // namespace host_effecters
-} // namespace pldm
diff --git a/host-bmc/dbus_to_terminus_effecters.cpp b/host-bmc/dbus_to_terminus_effecters.cpp
new file mode 100644
index 0000000..f11dc2f
--- /dev/null
+++ b/host-bmc/dbus_to_terminus_effecters.cpp
@@ -0,0 +1,683 @@
+#include "dbus_to_terminus_effecters.hpp"
+
+#include <libpldm/pdr.h>
+#include <libpldm/platform.h>
+
+#include <phosphor-logging/lg2.hpp>
+#include <xyz/openbmc_project/Common/error.hpp>
+#include <xyz/openbmc_project/State/Boot/Progress/client.hpp>
+#include <xyz/openbmc_project/State/OperatingSystem/Status/server.hpp>
+
+#include <fstream>
+
+PHOSPHOR_LOG2_USING;
+
+using namespace pldm::utils;
+
+namespace pldm
+{
+namespace host_effecters
+{
+using InternalFailure =
+    sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
+
+constexpr auto hostEffecterJson = "dbus_to_terminus_effecter.json";
+
+void HostEffecterParser::populatePropVals(
+    const Json& dBusValues, std::vector<PropertyValue>& propertyValues,
+    const std::string& propertyType)
+
+{
+    for (const auto& elem : dBusValues)
+    {
+        auto value = jsonEntryToDbusVal(propertyType, elem);
+        propertyValues.emplace_back(value);
+    }
+}
+
+void HostEffecterParser::parseEffecterJson(const std::string& jsonPath)
+{
+    fs::path jsonDir(jsonPath);
+    if (!fs::exists(jsonDir) || fs::is_empty(jsonDir))
+    {
+        error("Effecter json file for remote terminus '{PATH}' does not exist.",
+              "PATH", jsonPath);
+        return;
+    }
+
+    fs::path jsonFilePath = jsonDir / hostEffecterJson;
+    if (!fs::exists(jsonFilePath))
+    {
+        error("Json at path '{PATH}' does not exist.", "PATH", jsonFilePath);
+        throw InternalFailure();
+    }
+
+    std::ifstream jsonFile(jsonFilePath);
+    auto data = Json::parse(jsonFile, nullptr, false);
+    if (data.is_discarded())
+    {
+        error("Failed to parse json file {PATH}", "PATH", jsonFilePath);
+        throw InternalFailure();
+    }
+    const Json empty{};
+    const std::vector<Json> emptyList{};
+
+    auto entries = data.value("entries", emptyList);
+    for (const auto& entry : entries)
+    {
+        EffecterInfo effecterInfo;
+        effecterInfo.mctpEid = entry.value("mctp_eid", 0xFF);
+        auto jsonEffecterInfo = entry.value("effecter_info", empty);
+        auto effecterId =
+            jsonEffecterInfo.value("effecterID", PLDM_INVALID_EFFECTER_ID);
+        /* default as PLDM_STATE_EFFECTER_PDR */
+        auto effecterPdrType =
+            jsonEffecterInfo.value("effecterPdrType", PLDM_STATE_EFFECTER_PDR);
+        if (effecterPdrType != PLDM_STATE_EFFECTER_PDR &&
+            effecterPdrType != PLDM_NUMERIC_EFFECTER_PDR)
+        {
+            error(
+                "Effecter PDRType not supported {TYPE} of effecterID '{EFFECTERID}'",
+                "TYPE", effecterPdrType, "EFFECTERID", effecterId);
+            continue;
+        }
+        effecterInfo.effecterPdrType = effecterPdrType;
+        effecterInfo.containerId = jsonEffecterInfo.value("containerID", 0);
+        effecterInfo.entityType = jsonEffecterInfo.value("entityType", 0);
+        effecterInfo.entityInstance =
+            jsonEffecterInfo.value("entityInstance", 0);
+        effecterInfo.compEffecterCnt =
+            jsonEffecterInfo.value("compositeEffecterCount", 0);
+        effecterInfo.checkHostState =
+            jsonEffecterInfo.value("checkHostState", true);
+        auto effecters = entry.value("effecters", emptyList);
+
+        if (effecterPdrType == PLDM_NUMERIC_EFFECTER_PDR)
+        {
+            for (const auto& effecter : effecters)
+            {
+                DBusNumericEffecterMapping dbusInfo{};
+                auto jsonDbusInfo = effecter.value("dbus_info", empty);
+                dbusInfo.dataSize = effecter.value("effecterDataSize", 0);
+                dbusInfo.unitModifier = effecter.value("unitModifier", 0);
+                dbusInfo.resolution = effecter.value("resolution", 1);
+                dbusInfo.offset = effecter.value("offset", 0);
+                dbusInfo.dbusMap.objectPath =
+                    jsonDbusInfo.value("object_path", "");
+                dbusInfo.dbusMap.interface =
+                    jsonDbusInfo.value("interface", "");
+                dbusInfo.dbusMap.propertyName =
+                    jsonDbusInfo.value("property_name", "");
+                dbusInfo.dbusMap.propertyType =
+                    jsonDbusInfo.value("property_type", "");
+                /**
+                 * Only support these property type for Numeric Effecter D-Bus
+                 * property:
+                 * "uint8_t", "int16_t",  "uint16_t", "int32_t", "uint32_t",
+                 * "int64_t", "uint64_t", "double"
+                 */
+                if (!dbusValueNumericTypeNames.contains(
+                        dbusInfo.dbusMap.propertyType))
+                {
+                    lg2::error(
+                        "Invalid PropertyType {TYPE} of object path {PATH} property name {NAME}",
+                        "TYPE", dbusInfo.dbusMap.propertyType, "PATH",
+                        dbusInfo.dbusMap.objectPath, "NAME",
+                        dbusInfo.dbusMap.propertyName);
+                    continue;
+                }
+
+                dbusInfo.propertyValue =
+                    std::numeric_limits<double>::quiet_NaN();
+                auto effecterInfoIndex = hostEffecterInfo.size();
+                auto dbusInfoIndex = effecterInfo.dbusInfo.size();
+                createHostEffecterMatch(
+                    dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface,
+                    effecterInfoIndex, dbusInfoIndex, effecterId);
+                effecterInfo.dbusNumericEffecterInfo.emplace_back(
+                    std::move(dbusInfo));
+            }
+            hostEffecterInfo.emplace_back(std::move(effecterInfo));
+            continue;
+        }
+
+        for (const auto& effecter : effecters)
+        {
+            DBusEffecterMapping dbusInfo{};
+            auto jsonDbusInfo = effecter.value("dbus_info", empty);
+            dbusInfo.dbusMap.objectPath = jsonDbusInfo.value("object_path", "");
+            dbusInfo.dbusMap.interface = jsonDbusInfo.value("interface", "");
+            dbusInfo.dbusMap.propertyName =
+                jsonDbusInfo.value("property_name", "");
+            dbusInfo.dbusMap.propertyType =
+                jsonDbusInfo.value("property_type", "");
+            Json propertyValues = jsonDbusInfo["property_values"];
+
+            populatePropVals(propertyValues, dbusInfo.propertyValues,
+                             dbusInfo.dbusMap.propertyType);
+
+            const std::vector<uint8_t> emptyStates{};
+            auto state = effecter.value("state", empty);
+            dbusInfo.state.stateSetId = state.value("id", 0);
+            auto states = state.value("state_values", emptyStates);
+            if (dbusInfo.propertyValues.size() != states.size())
+            {
+                error(
+                    "Number of states do not match with number of D-Bus property values in the json. Object path at '{PATH}' and property '{PROPERTY}' will not be monitored",
+                    "PATH", dbusInfo.dbusMap.objectPath, "PROPERTY",
+                    dbusInfo.dbusMap.propertyName);
+                continue;
+            }
+            for (const auto& s : states)
+            {
+                dbusInfo.state.states.emplace_back(s);
+            }
+
+            auto effecterInfoIndex = hostEffecterInfo.size();
+            auto dbusInfoIndex = effecterInfo.dbusInfo.size();
+            createHostEffecterMatch(
+                dbusInfo.dbusMap.objectPath, dbusInfo.dbusMap.interface,
+                effecterInfoIndex, dbusInfoIndex, effecterId);
+            effecterInfo.dbusInfo.emplace_back(std::move(dbusInfo));
+        }
+        hostEffecterInfo.emplace_back(std::move(effecterInfo));
+    }
+}
+
+bool HostEffecterParser::isHostOn(void)
+{
+    using BootProgress =
+        sdbusplus::client::xyz::openbmc_project::state::boot::Progress<>;
+    constexpr auto hostStatePath = "/xyz/openbmc_project/state/host0";
+    try
+    {
+        auto propVal = dbusHandler->getDbusPropertyVariant(
+            hostStatePath, "BootProgress", BootProgress::interface);
+
+        using Stages = BootProgress::ProgressStages;
+        auto currHostState = sdbusplus::message::convert_from_string<Stages>(
+                                 std::get<std::string>(propVal))
+                                 .value();
+
+        if (currHostState != Stages::SystemInitComplete &&
+            currHostState != Stages::OSRunning &&
+            currHostState != Stages::SystemSetup &&
+            currHostState != Stages::OEM)
+        {
+            info(
+                "Remote terminus is not up/active, current remote terminus state is: '{CURRENT_HOST_STATE}'",
+                "CURRENT_HOST_STATE", currHostState);
+            return false;
+        }
+    }
+    catch (const sdbusplus::exception_t& e)
+    {
+        error(
+            "Error in getting current remote terminus state. Will still continue to set the remote terminus effecter, error - {ERROR}",
+            "ERROR", e);
+        return false;
+    }
+
+    return true;
+}
+
+void HostEffecterParser::processHostEffecterChangeNotification(
+    const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex,
+    size_t dbusInfoIndex, uint16_t effecterId)
+{
+    const auto& pdrType = hostEffecterInfo[effecterInfoIndex].effecterPdrType;
+    if (pdrType == PLDM_NUMERIC_EFFECTER_PDR)
+    {
+        processTerminusNumericEffecterChangeNotification(
+            chProperties, effecterInfoIndex, dbusInfoIndex, effecterId);
+        return;
+    }
+    const auto& propertyName = hostEffecterInfo[effecterInfoIndex]
+                                   .dbusInfo[dbusInfoIndex]
+                                   .dbusMap.propertyName;
+
+    const auto& it = chProperties.find(propertyName);
+
+    if (it == chProperties.end())
+    {
+        return;
+    }
+
+    if (effecterId == PLDM_INVALID_EFFECTER_ID)
+    {
+        constexpr auto localOrRemote = false;
+        effecterId = findStateEffecterId(
+            pdrRepo, hostEffecterInfo[effecterInfoIndex].entityType,
+            hostEffecterInfo[effecterInfoIndex].entityInstance,
+            hostEffecterInfo[effecterInfoIndex].containerId,
+            hostEffecterInfo[effecterInfoIndex]
+                .dbusInfo[dbusInfoIndex]
+                .state.stateSetId,
+            localOrRemote);
+        if (effecterId == PLDM_INVALID_EFFECTER_ID)
+        {
+            error(
+                "Effecter ID '{EFFECTERID}' of entity type '{TYPE}', entityInstance '{INSTANCE}' and containerID '{CONTAINER_ID}' not found in pdr repo",
+                "EFFECTERID", effecterId, "TYPE",
+                hostEffecterInfo[effecterInfoIndex].entityType, "INSTANCE",
+                hostEffecterInfo[effecterInfoIndex].entityInstance,
+                "CONTAINER_ID",
+                hostEffecterInfo[effecterInfoIndex].containerId);
+            return;
+        }
+    }
+
+    if (!isHostOn())
+    {
+        return;
+    }
+
+    uint8_t newState{};
+    try
+    {
+        newState =
+            findNewStateValue(effecterInfoIndex, dbusInfoIndex, it->second);
+    }
+    catch (const std::out_of_range& e)
+    {
+        error("Failed to find new state '{NEW_STATE}' in json, error - {ERROR}",
+              "ERROR", e, "NEW_STATE", newState);
+        return;
+    }
+
+    std::vector<set_effecter_state_field> stateField;
+    for (uint8_t i = 0; i < hostEffecterInfo[effecterInfoIndex].compEffecterCnt;
+         i++)
+    {
+        if (i == dbusInfoIndex)
+        {
+            stateField.push_back({PLDM_REQUEST_SET, newState});
+        }
+        else
+        {
+            stateField.push_back({PLDM_NO_CHANGE, 0});
+        }
+    }
+    int rc{};
+    try
+    {
+        rc = setHostStateEffecter(effecterInfoIndex, stateField, effecterId);
+    }
+    catch (const std::runtime_error& e)
+    {
+        error(
+            "Failed to set remote terminus state effecter for effecter ID '{EFFECTERID}', error - {ERROR}",
+            "ERROR", e, "EFFECTERID", effecterId);
+        return;
+    }
+    if (rc != PLDM_SUCCESS)
+    {
+        error(
+            "Failed to set the remote terminus state effecter for effecter ID '{EFFECTERID}', response code '{RC}'",
+            "EFFECTERID", effecterId, "RC", rc);
+    }
+}
+
+double HostEffecterParser::adjustValue(double value, double offset,
+                                       double resolution, int8_t modify)
+{
+    double unitModifier = std::pow(10, signed(modify));
+    return std::round((value - offset) * resolution / unitModifier);
+}
+
+void HostEffecterParser::processTerminusNumericEffecterChangeNotification(
+    const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex,
+    size_t dbusInfoIndex, uint16_t effecterId)
+{
+    const auto& checkHost = hostEffecterInfo[effecterInfoIndex].checkHostState;
+    const auto& propValues = hostEffecterInfo[effecterInfoIndex]
+                                 .dbusNumericEffecterInfo[dbusInfoIndex];
+    const auto& propertyName = propValues.dbusMap.propertyName;
+    const auto& propertyType = propValues.dbusMap.propertyType;
+
+    if (effecterId == PLDM_INVALID_EFFECTER_ID)
+    {
+        lg2::error(
+            "Dbus to PLDM Numeric Effecter setting requires valid effecter ID. Invalid effecter ID {EFFECTER_ID}",
+            "EFFECTER_ID", effecterId);
+    }
+
+    if (!dbusValueNumericTypeNames.contains(propertyType))
+    {
+        lg2::error(
+            "DBus Value to PLDM Numeric Effecter setting only supports D-Bus Numeric data type. Invalid type {TYPE}",
+            "TYPE", propertyType);
+        return;
+    }
+
+    const auto& it = chProperties.find(propertyName);
+
+    if (it == chProperties.end())
+    {
+        return;
+    }
+
+    double val = std::numeric_limits<double>::quiet_NaN();
+    if (!pldm::utils::dbusPropValuesToDouble(propertyType, it->second, &val))
+    {
+        lg2::error(
+            "DBus Value to PLDM Numeric Effecter setting only supports Numeric D-Bus data type. Invalid type {TYPE}",
+            "TYPE", propertyType);
+        return;
+    }
+
+    /* Update the current value of D-Bus interface*/
+    if (!std::isnan(val) && std::isnan(propValues.propertyValue))
+    {
+        hostEffecterInfo[effecterInfoIndex]
+            .dbusNumericEffecterInfo[dbusInfoIndex]
+            .propertyValue = val;
+        return;
+    }
+
+    /* Bypass the setting when the current value is NA or settting value is NA*/
+    if (std::isnan(propValues.propertyValue) || std::isnan(val))
+    {
+        return;
+    }
+
+    /* Setting value equals the D-Bus value which is real value of effecter */
+    if (val == propValues.propertyValue)
+    {
+        return;
+    }
+
+    double rawValue = adjustValue(val, propValues.offset, propValues.resolution,
+                                  propValues.unitModifier);
+
+    if (checkHost && !isHostOn())
+    {
+        return;
+    }
+
+    try
+    {
+        auto rc = setTerminusNumericEffecter(effecterInfoIndex, effecterId,
+                                             propValues.dataSize, rawValue);
+        if (rc)
+        {
+            error(
+                "Could not set the numeric effecter ID '{EFFECTERID}' return code '{RC}'",
+                "EFFECTERID", effecterId, "RC", rc);
+            return;
+        }
+    }
+    catch (const std::runtime_error& e)
+    {
+        error("Could not set numeric effecter ID= '{EFFECTERID}'", "EFFECTERID",
+              effecterId);
+        return;
+    }
+
+    hostEffecterInfo[effecterInfoIndex]
+        .dbusNumericEffecterInfo[dbusInfoIndex]
+        .propertyValue = val;
+
+    return;
+}
+
+uint8_t HostEffecterParser::findNewStateValue(
+    size_t effecterInfoIndex, size_t dbusInfoIndex,
+    const PropertyValue& propertyValue)
+{
+    const auto& propValues = hostEffecterInfo[effecterInfoIndex]
+                                 .dbusInfo[dbusInfoIndex]
+                                 .propertyValues;
+    auto it = std::find(propValues.begin(), propValues.end(), propertyValue);
+    uint8_t newState{};
+    if (it != propValues.end())
+    {
+        auto index = std::distance(propValues.begin(), it);
+        newState = hostEffecterInfo[effecterInfoIndex]
+                       .dbusInfo[dbusInfoIndex]
+                       .state.states[index];
+    }
+    else
+    {
+        throw std::out_of_range("new state not found in json");
+    }
+    return newState;
+}
+
+size_t getEffecterDataSize(uint8_t effecterDataSize)
+{
+    switch (effecterDataSize)
+    {
+        case PLDM_EFFECTER_DATA_SIZE_UINT8:
+            return sizeof(uint8_t);
+        case PLDM_EFFECTER_DATA_SIZE_SINT8:
+            return sizeof(int8_t);
+        case PLDM_EFFECTER_DATA_SIZE_UINT16:
+            return sizeof(uint16_t);
+        case PLDM_EFFECTER_DATA_SIZE_SINT16:
+            return sizeof(int16_t);
+        case PLDM_EFFECTER_DATA_SIZE_UINT32:
+            return sizeof(uint32_t);
+        case PLDM_EFFECTER_DATA_SIZE_SINT32:
+            return sizeof(int32_t);
+        default:
+            return 0;
+    }
+}
+
+int HostEffecterParser::setTerminusNumericEffecter(
+    size_t effecterInfoIndex, uint16_t effecterId, uint8_t dataSize,
+    double rawValue)
+{
+    uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid;
+    auto instanceId = instanceIdDb->next(mctpEid);
+    int rc = PLDM_ERROR;
+    std::vector<uint8_t> requestMsg;
+
+    /**
+     * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES = 4. It includes the 1 byte
+     * value for effecterValue as `Table 48 - SetNumericEffecterValue command
+     * format` DSP0248 V1.3.0 So the payload_length of `SetNumericEffecterValue`
+     * request message will be payload_length =
+     * PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 + sizeof(dataType)
+     */
+    size_t payload_length = PLDM_SET_NUMERIC_EFFECTER_VALUE_MIN_REQ_BYTES - 1 +
+                            getEffecterDataSize(dataSize);
+    requestMsg.resize(sizeof(pldm_msg_hdr) + payload_length);
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    switch (dataSize)
+    {
+        case PLDM_EFFECTER_DATA_SIZE_UINT8:
+        {
+            auto value_uint8 = (uint8_t)rawValue;
+            rc = encode_set_numeric_effecter_value_req(
+                instanceId, effecterId, dataSize,
+                reinterpret_cast<uint8_t*>(&value_uint8), request,
+                payload_length);
+            break;
+        }
+        case PLDM_EFFECTER_DATA_SIZE_SINT8:
+        {
+            auto value_int8 = (int8_t)rawValue;
+            rc = encode_set_numeric_effecter_value_req(
+                instanceId, effecterId, dataSize,
+                reinterpret_cast<uint8_t*>(&value_int8), request,
+                payload_length);
+            break;
+        }
+        case PLDM_EFFECTER_DATA_SIZE_UINT16:
+        {
+            auto value_uint16 = (uint16_t)rawValue;
+            rc = encode_set_numeric_effecter_value_req(
+                instanceId, effecterId, dataSize,
+                reinterpret_cast<uint8_t*>(&value_uint16), request,
+                payload_length);
+            break;
+        }
+        case PLDM_EFFECTER_DATA_SIZE_SINT16:
+        {
+            auto value_int16 = (int16_t)rawValue;
+            rc = encode_set_numeric_effecter_value_req(
+                instanceId, effecterId, dataSize,
+                reinterpret_cast<uint8_t*>(&value_int16), request,
+                payload_length);
+            break;
+        }
+        case PLDM_EFFECTER_DATA_SIZE_UINT32:
+        {
+            auto value_uint32 = (uint32_t)rawValue;
+            rc = encode_set_numeric_effecter_value_req(
+                instanceId, effecterId, dataSize,
+                reinterpret_cast<uint8_t*>(&value_uint32), request,
+                payload_length);
+            break;
+        }
+        case PLDM_EFFECTER_DATA_SIZE_SINT32:
+        {
+            auto value_int32 = (int32_t)rawValue;
+            rc = encode_set_numeric_effecter_value_req(
+                instanceId, effecterId, dataSize,
+                reinterpret_cast<uint8_t*>(&value_int32), request,
+                payload_length);
+            break;
+        }
+        default:
+            break;
+    }
+
+    if (rc)
+    {
+        error(
+            "Failed to encode set numeric effecter request message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with error code '{RC}'",
+            "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex,
+            rc);
+
+        instanceIdDb->free(mctpEid, instanceId);
+        return rc;
+    }
+
+    auto setNumericEffecterRespHandler = [effecterId](mctp_eid_t /*eid*/,
+                                                      const pldm_msg* response,
+                                                      size_t respMsgLen) {
+        if (response == nullptr || !respMsgLen)
+        {
+            error(
+                "Failed to receive response for setNumericEffecterValue command");
+            return;
+        }
+        uint8_t completionCode{};
+        auto rc = decode_set_numeric_effecter_value_resp(response, respMsgLen,
+                                                         &completionCode);
+
+        if (rc)
+        {
+            error(
+                "Failed to decode set numeric effecter response message for effecter ID '{EFFECTERID}' with error code '{RC}'",
+                "EFFECTERID", effecterId, "RC", lg2::hex, rc);
+        }
+        if (completionCode)
+        {
+            error(
+                "Failed to set numeric effecter for effecter ID '{EFFECTERID}' with complete code '{CC}'",
+                "EFFECTERID", effecterId, "CC", lg2::hex, completionCode);
+        }
+    };
+
+    rc = handler->registerRequest(
+        mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_NUMERIC_EFFECTER_VALUE,
+        std::move(requestMsg), std::move(setNumericEffecterRespHandler));
+    if (rc)
+    {
+        error("Failed to send request to set an effecter on Host");
+    }
+    return rc;
+}
+
+int HostEffecterParser::setHostStateEffecter(
+    size_t effecterInfoIndex, std::vector<set_effecter_state_field>& stateField,
+    uint16_t effecterId)
+{
+    uint8_t& mctpEid = hostEffecterInfo[effecterInfoIndex].mctpEid;
+    uint8_t& compEffCnt = hostEffecterInfo[effecterInfoIndex].compEffecterCnt;
+    auto instanceId = instanceIdDb->next(mctpEid);
+
+    std::vector<uint8_t> requestMsg(
+        sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(compEffCnt) +
+            sizeof(set_effecter_state_field) * compEffCnt,
+        0);
+    auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+    auto rc = encode_set_state_effecter_states_req(
+        instanceId, effecterId, compEffCnt, stateField.data(), request);
+
+    if (rc != PLDM_SUCCESS)
+    {
+        error(
+            "Failed to encode set state effecter states message for effecter ID '{EFFECTERID}' and instanceID '{INSTANCE}' with response code '{RC}'",
+            "EFFECTERID", effecterId, "INSTANCE", instanceId, "RC", lg2::hex,
+            rc);
+        instanceIdDb->free(mctpEid, instanceId);
+        return rc;
+    }
+
+    auto setStateEffecterStatesRespHandler = [](mctp_eid_t /*eid*/,
+                                                const pldm_msg* response,
+                                                size_t respMsgLen) {
+        if (response == nullptr || !respMsgLen)
+        {
+            error(
+                "Failed to receive response for setting state effecter states.");
+            return;
+        }
+        uint8_t completionCode{};
+        auto rc = decode_set_state_effecter_states_resp(response, respMsgLen,
+                                                        &completionCode);
+        if (rc)
+        {
+            error(
+                "Failed to decode response of set state effecter states, response code '{RC}'",
+                "RC", rc);
+            pldm::utils::reportError(
+                "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed");
+        }
+        if (completionCode)
+        {
+            error(
+                "Failed to set a remote terminus effecter, completion code '{CC}'",
+                "CC", completionCode);
+            pldm::utils::reportError(
+                "xyz.openbmc_project.bmc.pldm.SetHostEffecterFailed");
+        }
+    };
+
+    rc = handler->registerRequest(
+        mctpEid, instanceId, PLDM_PLATFORM, PLDM_SET_STATE_EFFECTER_STATES,
+        std::move(requestMsg), std::move(setStateEffecterStatesRespHandler));
+    if (rc)
+    {
+        error(
+            "Failed to send request to set an effecter on remote terminus for effecter ID '{EFFECTERID}', response code '{RC}'",
+            "EFFECTERID", effecterId, "RC", rc);
+    }
+    return rc;
+}
+
+void HostEffecterParser::createHostEffecterMatch(
+    const std::string& objectPath, const std::string& interface,
+    size_t effecterInfoIndex, size_t dbusInfoIndex, uint16_t effecterId)
+{
+    using namespace sdbusplus::bus::match::rules;
+    effecterInfoMatch.emplace_back(std::make_unique<sdbusplus::bus::match_t>(
+        pldm::utils::DBusHandler::getBus(),
+        propertiesChanged(objectPath, interface),
+        [this, effecterInfoIndex, dbusInfoIndex,
+         effecterId](sdbusplus::message_t& msg) {
+            DbusChgHostEffecterProps props;
+            std::string iface;
+            msg.read(iface, props);
+            processHostEffecterChangeNotification(props, effecterInfoIndex,
+                                                  dbusInfoIndex, effecterId);
+        }));
+}
+
+} // namespace host_effecters
+} // namespace pldm
diff --git a/host-bmc/dbus_to_host_effecters.hpp b/host-bmc/dbus_to_terminus_effecters.hpp
similarity index 68%
rename from host-bmc/dbus_to_host_effecters.hpp
rename to host-bmc/dbus_to_terminus_effecters.hpp
index 7591381..8e4357e 100644
--- a/host-bmc/dbus_to_host_effecters.hpp
+++ b/host-bmc/dbus_to_terminus_effecters.hpp
@@ -43,18 +43,35 @@
     PossibleState state; //!< Corresponding effecter states
 };
 
+/** @struct DBusEffecterMapping
+ *  Contains the D-Bus information for an effecter
+ */
+struct DBusNumericEffecterMapping
+{
+    pldm::utils::DBusMapping dbusMap;
+    uint8_t dataSize;     //!< Numeric effecter PDR data size
+    double resolution;    //!< Numeric effecter PDR resolution
+    double offset;        //!< Numeric effecter PDR offset
+    int8_t unitModifier;  //!< Numeric effecter PDR unitModifier
+    double propertyValue; //!< D-Bus property values
+};
+
 /** @struct EffecterInfo
  *  Contains the effecter information as a whole
  */
 struct EffecterInfo
 {
-    uint8_t mctpEid;         //!< Host mctp eid
-    uint16_t containerId;    //!< Container Id for host effecter
-    uint16_t entityType;     //!< Entity type for the host effecter
-    uint16_t entityInstance; //!< Entity instance for the host effecter
-    uint8_t compEffecterCnt; //!< Composite effecter count
+    uint8_t mctpEid;             //!< Host mctp eid
+    uint8_t effecterPdrType;     //!< Effecter PDR type state/numeric
+    uint16_t containerId;        //!< Container Id for host effecter
+    uint16_t entityType;         //!< Entity type for the host effecter
+    uint16_t entityInstance;     //!< Entity instance for the host effecter
+    uint8_t compEffecterCnt;     //!< Composite effecter count
+    bool checkHostState;         //!< Check host state before setting effecter
     std::vector<DBusEffecterMapping>
-        dbusInfo;            //!< D-Bus information for the effecter id
+        dbusInfo;                //!< D-Bus information for the effecter id
+    std::vector<DBusNumericEffecterMapping>
+        dbusNumericEffecterInfo; //!< D-Bus information for the effecter id
 };
 
 /** @class HostEffecterParser
@@ -120,6 +137,20 @@
         const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex,
         size_t dbusInfoIndex, uint16_t effecterId);
 
+    /* @brief Method to take action when the subscribed D-Bus property is
+     *        changed
+     * @param[in] chProperties - list of properties which have changed
+     * @param[in] effecterInfoIndex - index of effecterInfo pointer in
+     *                                hostEffecterInfo
+     * @param[in] dbusInfoIndex - index on dbusInfo pointer in each effecterInfo
+
+     * @param[in] effecterId - terminus numeric effecter id
+     * @return - none
+     */
+    void processTerminusNumericEffecterChangeNotification(
+        const DbusChgHostEffecterProps& chProperties, size_t effecterInfoIndex,
+        size_t dbusInfoIndex, uint16_t effecterId);
+
     /* @brief Populate the property values in each dbusInfo from the json
      *
      * @param[in] dBusValues - json values
@@ -145,6 +176,19 @@
         size_t effecterInfoIndex,
         std::vector<set_effecter_state_field>& stateField, uint16_t effecterId);
 
+    /* @brief Set a terminus numeric effecter
+     *
+     * @param[in] effecterInfoIndex - index of effecterInfo pointer in
+     *                                hostEffecterInfo
+     * @param[in] effecterId - host effecter id
+     * @param[in] dataSize - data size
+     * @param[in] rawValue - raw value
+     * @return - PLDM status code
+     */
+    virtual int setTerminusNumericEffecter(size_t effecterInfoIndex,
+                                           uint16_t effecterId,
+                                           uint8_t dataSize, double rawValue);
+
     /* @brief Fetches the new state value and the index in stateField set which
      *        needs to be set with the new value in the setStateEffecter call
      * @param[in] effecterInfoIndex - index of effecterInfo in hostEffecterInfo
@@ -156,7 +200,7 @@
                               const pldm::utils::PropertyValue& propertyValue);
 
     /* @brief Subscribes for D-Bus property change signal on the specified
-     * object
+     *        object
      *
      * @param[in] objectPath - D-Bus object path to look for
      * @param[in] interface - D-Bus interface
@@ -169,6 +213,26 @@
         const std::string& objectPath, const std::string& interface,
         size_t effecterInfoIndex, size_t dbusInfoIndex, uint16_t effecterId);
 
+    /* @brief Adjust the nummeric effecter value base on the effecter
+     *        configurations
+     *
+     * @param[in] value - Raw value
+     * @param[in] offset - offset config
+     * @param[in] resolution - resolution config
+     * @param[in] modify - modify config
+     *
+     * @return - Value of effecter
+     */
+    double adjustValue(double value, double offset, double resolution,
+                       int8_t modify);
+
+  private:
+    /* @brief Verify host On state before configure the host effecters
+     *
+     * @return - true if host is on and false for others cases
+     */
+    bool isHostOn(void);
+
   protected:
     pldm::InstanceIdDb* instanceIdDb; //!< Reference to the InstanceIdDb object
                                       //!< to obtain instance id
diff --git a/host-bmc/test/dbus_to_host_effecter_test.cpp b/host-bmc/test/dbus_to_host_effecter_test.cpp
deleted file mode 100644
index 00653ce..0000000
--- a/host-bmc/test/dbus_to_host_effecter_test.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "common/test/mocked_utils.hpp"
-#include "common/utils.hpp"
-#include "host-bmc/dbus_to_host_effecters.hpp"
-
-#include <nlohmann/json.hpp>
-
-#include <gtest/gtest.h>
-
-using namespace pldm::host_effecters;
-using namespace pldm::utils;
-
-class MockHostEffecterParser : public HostEffecterParser
-{
-  public:
-    MockHostEffecterParser(int fd, const pldm_pdr* repo,
-                           DBusHandler* const dbusHandler,
-                           const std::string& jsonPath) :
-        HostEffecterParser(nullptr, fd, repo, dbusHandler, jsonPath, nullptr)
-    {}
-
-    MOCK_METHOD(int, setHostStateEffecter,
-                (size_t, std::vector<set_effecter_state_field>&, uint16_t),
-                (override));
-
-    MOCK_METHOD(void, createHostEffecterMatch,
-                (const std::string&, const std::string&, size_t, size_t,
-                 uint16_t),
-                (override));
-
-    const std::vector<EffecterInfo>& gethostEffecterInfo()
-    {
-        return hostEffecterInfo;
-    }
-};
-
-TEST(HostEffecterParser, parseEffecterJsonGoodPath)
-{
-    MockdBusHandler dbusHandler;
-    int sockfd{};
-    MockHostEffecterParser hostEffecterParserGood(sockfd, nullptr, &dbusHandler,
-                                                  "./host_effecter_jsons/good");
-    auto hostEffecterInfo = hostEffecterParserGood.gethostEffecterInfo();
-    ASSERT_EQ(hostEffecterInfo.size(), 1);
-    ASSERT_EQ(hostEffecterInfo[0].entityInstance, 0);
-    ASSERT_EQ(hostEffecterInfo[0].entityType, 33);
-    ASSERT_EQ(hostEffecterInfo[0].dbusInfo.size(), 1);
-    DBusEffecterMapping dbusInfo{
-        {"/xyz/openbmc_project/control/host0/boot",
-         "xyz.openbmc_project.Control.Boot.Mode", "BootMode", "string"},
-        {"xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"},
-        {196, {2}}};
-    auto& temp = hostEffecterInfo[0].dbusInfo[0];
-    ASSERT_EQ(temp.dbusMap.objectPath == dbusInfo.dbusMap.objectPath, true);
-    ASSERT_EQ(temp.dbusMap.interface == dbusInfo.dbusMap.interface, true);
-    ASSERT_EQ(temp.dbusMap.propertyName == dbusInfo.dbusMap.propertyName, true);
-    ASSERT_EQ(temp.dbusMap.propertyType == dbusInfo.dbusMap.propertyType, true);
-}
-
-TEST(HostEffecterParser, parseEffecterJsonBadPath)
-{
-    MockdBusHandler dbusHandler;
-    int sockfd{};
-    MockHostEffecterParser hostEffecterParser(sockfd, nullptr, &dbusHandler,
-                                              "./host_effecter_jsons/no_json");
-    ASSERT_THROW(
-        hostEffecterParser.parseEffecterJson("./host_effecter_jsons/no_json"),
-        std::exception);
-    ASSERT_THROW(
-        hostEffecterParser.parseEffecterJson("./host_effecter_jsons/malformed"),
-        std::exception);
-}
-
-TEST(HostEffecterParser, findNewStateValue)
-{
-    MockdBusHandler dbusHandler;
-    int sockfd{};
-    MockHostEffecterParser hostEffecterParser(sockfd, nullptr, &dbusHandler,
-                                              "./host_effecter_jsons/good");
-
-    PropertyValue val1{std::in_place_type<std::string>,
-                       "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"};
-    PropertyValue val2{std::in_place_type<std::string>,
-                       "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup"};
-    auto newState = hostEffecterParser.findNewStateValue(0, 0, val1);
-    ASSERT_EQ(newState, 2);
-
-    ASSERT_THROW(hostEffecterParser.findNewStateValue(0, 0, val2),
-                 std::exception);
-}
diff --git a/host-bmc/test/dbus_to_terminus_effecter_test.cpp b/host-bmc/test/dbus_to_terminus_effecter_test.cpp
new file mode 100644
index 0000000..f8ff8d6
--- /dev/null
+++ b/host-bmc/test/dbus_to_terminus_effecter_test.cpp
@@ -0,0 +1,143 @@
+#include "common/test/mocked_utils.hpp"
+#include "common/utils.hpp"
+#include "host-bmc/dbus_to_terminus_effecters.hpp"
+
+#include <nlohmann/json.hpp>
+
+#include <gtest/gtest.h>
+
+using namespace pldm::host_effecters;
+using namespace pldm::utils;
+
+class MockHostEffecterParser : public HostEffecterParser
+{
+  public:
+    MockHostEffecterParser(int fd, const pldm_pdr* repo,
+                           DBusHandler* const dbusHandler,
+                           const std::string& jsonPath) :
+        HostEffecterParser(nullptr, fd, repo, dbusHandler, jsonPath, nullptr)
+    {}
+
+    MOCK_METHOD(int, setHostStateEffecter,
+                (size_t, std::vector<set_effecter_state_field>&, uint16_t),
+                (override));
+
+    MOCK_METHOD(void, createHostEffecterMatch,
+                (const std::string&, const std::string&, size_t, size_t,
+                 uint16_t),
+                (override));
+
+    const std::vector<EffecterInfo>& gethostEffecterInfo()
+    {
+        return hostEffecterInfo;
+    }
+};
+
+TEST(HostEffecterParser, parseEffecterJsonGoodPath)
+{
+    MockdBusHandler dbusHandler;
+    int sockfd{};
+    MockHostEffecterParser hostEffecterParserGood(sockfd, nullptr, &dbusHandler,
+                                                  "./host_effecter_jsons/good");
+    auto hostEffecterInfo = hostEffecterParserGood.gethostEffecterInfo();
+    ASSERT_EQ(hostEffecterInfo.size(), 2);
+    ASSERT_EQ(hostEffecterInfo[0].effecterPdrType, PLDM_STATE_EFFECTER_PDR);
+    ASSERT_EQ(hostEffecterInfo[0].entityInstance, 0);
+    ASSERT_EQ(hostEffecterInfo[0].entityType, 33);
+    ASSERT_EQ(hostEffecterInfo[0].dbusInfo.size(), 1);
+    ASSERT_EQ(hostEffecterInfo[0].checkHostState, true);
+    DBusEffecterMapping dbusInfo{
+        {"/xyz/openbmc_project/control/host0/boot",
+         "xyz.openbmc_project.Control.Boot.Mode", "BootMode", "string"},
+        {"xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"},
+        {196, {2}}};
+    auto& temp = hostEffecterInfo[0].dbusInfo[0];
+    ASSERT_EQ(temp.dbusMap.objectPath == dbusInfo.dbusMap.objectPath, true);
+    ASSERT_EQ(temp.dbusMap.interface == dbusInfo.dbusMap.interface, true);
+    ASSERT_EQ(temp.dbusMap.propertyName == dbusInfo.dbusMap.propertyName, true);
+    ASSERT_EQ(temp.dbusMap.propertyType == dbusInfo.dbusMap.propertyType, true);
+
+    /* Check Numeric Effecter in Good Json file */
+    ASSERT_EQ(hostEffecterInfo[1].effecterPdrType, PLDM_NUMERIC_EFFECTER_PDR);
+    ASSERT_EQ(hostEffecterInfo[1].entityType, 32903);
+    ASSERT_EQ(hostEffecterInfo[1].entityInstance, 6);
+    ASSERT_EQ(hostEffecterInfo[1].containerId, 4);
+    ASSERT_EQ(hostEffecterInfo[1].dbusNumericEffecterInfo.size(), 1);
+    ASSERT_EQ(hostEffecterInfo[1].checkHostState, false);
+    DBusNumericEffecterMapping dbusInfoNumeric{
+        {"/xyz/openbmc_project/effecters/power/PLimit",
+         "xyz.openbmc_project.Effecter.Value", "Value", "double"},
+        5,
+        1,
+        0,
+        -3,
+        100};
+    auto& tempNumeric = hostEffecterInfo[1].dbusNumericEffecterInfo[0];
+    ASSERT_EQ(tempNumeric.dbusMap.objectPath ==
+                  dbusInfoNumeric.dbusMap.objectPath,
+              true);
+    ASSERT_EQ(tempNumeric.dbusMap.interface ==
+                  dbusInfoNumeric.dbusMap.interface,
+              true);
+    ASSERT_EQ(tempNumeric.dbusMap.propertyName ==
+                  dbusInfoNumeric.dbusMap.propertyName,
+              true);
+    ASSERT_EQ(tempNumeric.dbusMap.propertyType ==
+                  dbusInfoNumeric.dbusMap.propertyType,
+              true);
+    ASSERT_EQ(tempNumeric.dataSize == dbusInfoNumeric.dataSize, true);
+    ASSERT_EQ(tempNumeric.resolution == dbusInfoNumeric.resolution, true);
+    ASSERT_EQ(tempNumeric.offset == dbusInfoNumeric.offset, true);
+    ASSERT_EQ(tempNumeric.unitModifier == dbusInfoNumeric.unitModifier, true);
+}
+
+TEST(HostEffecterParser, parseEffecterJsonBadPath)
+{
+    MockdBusHandler dbusHandler;
+    int sockfd{};
+    MockHostEffecterParser hostEffecterParser(sockfd, nullptr, &dbusHandler,
+                                              "./host_effecter_jsons/no_json");
+    ASSERT_THROW(
+        hostEffecterParser.parseEffecterJson("./host_effecter_jsons/no_json"),
+        std::exception);
+    ASSERT_THROW(
+        hostEffecterParser.parseEffecterJson("./host_effecter_jsons/malformed"),
+        std::exception);
+}
+
+TEST(HostEffecterParser, findNewStateValue)
+{
+    MockdBusHandler dbusHandler;
+    int sockfd{};
+    MockHostEffecterParser hostEffecterParser(sockfd, nullptr, &dbusHandler,
+                                              "./host_effecter_jsons/good");
+
+    PropertyValue val1{std::in_place_type<std::string>,
+                       "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"};
+    PropertyValue val2{std::in_place_type<std::string>,
+                       "xyz.openbmc_project.Control.Boot.Mode.Modes.Setup"};
+    auto newState = hostEffecterParser.findNewStateValue(0, 0, val1);
+    ASSERT_EQ(newState, 2);
+
+    ASSERT_THROW(hostEffecterParser.findNewStateValue(0, 0, val2),
+                 std::exception);
+}
+
+TEST(HostEffecterParser, adjustValue)
+{
+    MockdBusHandler dbusHandler;
+    int sockfd{};
+    MockHostEffecterParser hostEffecterParser(sockfd, nullptr, &dbusHandler,
+                                              "./host_effecter_jsons/good");
+
+    auto realVal = hostEffecterParser.adjustValue(200, -50, 0.5, -2);
+    ASSERT_EQ(realVal, 12500);
+    realVal = hostEffecterParser.adjustValue(0, -50, 1, 0);
+    ASSERT_EQ(realVal, 50);
+    realVal = hostEffecterParser.adjustValue(0, 100, 1, -1);
+    ASSERT_EQ(realVal, -1000);
+    realVal = hostEffecterParser.adjustValue(2.34, 0, 1, -1);
+    ASSERT_EQ(realVal, 23);
+    realVal = hostEffecterParser.adjustValue(2.35, 0, 1, -1);
+    ASSERT_EQ(realVal, 24);
+}
diff --git a/host-bmc/test/host_effecter_jsons/good/dbus_to_host_effecter.json b/host-bmc/test/host_effecter_jsons/good/dbus_to_host_effecter.json
deleted file mode 100644
index 5ae694c..0000000
--- a/host-bmc/test/host_effecter_jsons/good/dbus_to_host_effecter.json
+++ /dev/null
@@ -1,31 +0,0 @@
-{
-    "entries": [
-        {
-            "mctp_eid": 9,
-            "effecter_info": {
-                "effecterID": 4,
-                "containerID": 0,
-                "entityType": 33,
-                "entityInstance": 0,
-                "compositeEffecterCount": 1
-            },
-            "effecters": [
-                {
-                    "dbus_info": {
-                        "object_path": "/xyz/openbmc_project/control/host0/boot",
-                        "interface": "xyz.openbmc_project.Control.Boot.Mode",
-                        "property_name": "BootMode",
-                        "property_type": "string",
-                        "property_values": [
-                            "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"
-                        ]
-                    },
-                    "state": {
-                        "id": 196,
-                        "state_values": [2]
-                    }
-                }
-            ]
-        }
-    ]
-}
diff --git a/host-bmc/test/host_effecter_jsons/good/dbus_to_terminus_effecter.json b/host-bmc/test/host_effecter_jsons/good/dbus_to_terminus_effecter.json
new file mode 100644
index 0000000..2bc789a
--- /dev/null
+++ b/host-bmc/test/host_effecter_jsons/good/dbus_to_terminus_effecter.json
@@ -0,0 +1,57 @@
+{
+    "entries": [
+        {
+            "mctp_eid": 9,
+            "effecter_info": {
+                "effecterID": 4,
+                "containerID": 0,
+                "entityType": 33,
+                "entityInstance": 0,
+                "compositeEffecterCount": 1
+            },
+            "effecters": [
+                {
+                    "dbus_info": {
+                        "object_path": "/xyz/openbmc_project/control/host0/boot",
+                        "interface": "xyz.openbmc_project.Control.Boot.Mode",
+                        "property_name": "BootMode",
+                        "property_type": "string",
+                        "property_values": [
+                            "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"
+                        ]
+                    },
+                    "state": {
+                        "id": 196,
+                        "state_values": [2]
+                    }
+                }
+            ]
+        },
+        {
+            "mctp_eid": 20,
+            "effecter_info": {
+                "effecterPdrType": 9,
+                "effecterID": 155,
+                "entityType": 32903,
+                "entityInstance": 6,
+                "containerID": 4,
+                "compositeEffecterCount": 1,
+                "checkHostState": false
+            },
+            "effecters": [
+                {
+                    "dbus_info": {
+                        "object_path": "/xyz/openbmc_project/effecters/power/PLimit",
+                        "interface": "xyz.openbmc_project.Effecter.Value",
+                        "property_name": "Value",
+                        "property_type": "double"
+                    },
+                    "effecterDataSize": 5,
+                    "resolution": 1,
+                    "offset": 0,
+                    "unitModifier": -3
+                }
+            ]
+        }
+    ]
+}
diff --git a/host-bmc/test/host_effecter_jsons/malformed/dbus_to_host_effecter.json b/host-bmc/test/host_effecter_jsons/malformed/dbus_to_terminus_effecter.json
similarity index 100%
rename from host-bmc/test/host_effecter_jsons/malformed/dbus_to_host_effecter.json
rename to host-bmc/test/host_effecter_jsons/malformed/dbus_to_terminus_effecter.json
diff --git a/host-bmc/test/meson.build b/host-bmc/test/meson.build
index 9f762ed..c1d429d 100644
--- a/host-bmc/test/meson.build
+++ b/host-bmc/test/meson.build
@@ -1,5 +1,5 @@
 host_bmc_test_src = declare_dependency(
-    sources: ['../dbus_to_host_effecters.cpp'],
+    sources: ['../dbus_to_terminus_effecters.cpp'],
     include_directories: '../../requester',
 )
 
@@ -13,7 +13,7 @@
     '../dbus/pcie_slot.cpp',
 ]
 
-tests = ['dbus_to_host_effecter_test', 'utils_test', 'custom_dbus_test']
+tests = ['dbus_to_terminus_effecter_test', 'utils_test', 'custom_dbus_test']
 
 foreach t : tests
     test(