libpldmresponder: Implement GetStateSensorReadings

Register the getStateSensorReadings method and get the state sensor PDR
structure according to the SensorId property.

Tested with JSON file:
https://gist.github.com/lxwinspur/6a40abea7330c25e4d49826e890c4be9

pldmtool raw -d 0x80 0x02 0x21 0x01 0x00 0x01 0x00
Request Message:
08 01 80 02 21 01 00 01 00
Response Message:
08 01 00 02 21 00 01 03 00 00 00

Signed-off-by: George Liu <liuxiwei@inspur.com>
Change-Id: I4faeb1e85f9fd4a2745f592d37be38c28112f5b9
diff --git a/libpldmresponder/platform_state_sensor.hpp b/libpldmresponder/platform_state_sensor.hpp
new file mode 100644
index 0000000..3fd55cd
--- /dev/null
+++ b/libpldmresponder/platform_state_sensor.hpp
@@ -0,0 +1,157 @@
+#pragma once
+
+#include "config.h"
+
+#include "libpldm/platform.h"
+#include "libpldm/states.h"
+
+#include "common/utils.hpp"
+#include "libpldmresponder/pdr.hpp"
+#include "pdr_utils.hpp"
+#include "pldmd/handler.hpp"
+
+#include <cstdint>
+#include <map>
+
+using namespace pldm::responder::pdr;
+
+namespace pldm
+{
+namespace responder
+{
+namespace platform_state_sensor
+{
+
+/** @brief Function to get the sensor state
+ *
+ *  @tparam[in] DBusInterface - DBus interface type
+ *  @param[in] dBusIntf - The interface object of DBusInterface
+ *  @param[in] stateToDbusValue - Map of DBus property State to attribute value
+ *  @param[in] dbusMapping - The d-bus object
+ *
+ *  @return - Enumeration of SensorState
+ */
+template <class DBusInterface>
+uint8_t getStateSensorEventState(
+    const DBusInterface& dBusIntf,
+    const std::map<State, pldm::utils::PropertyValue>& stateToDbusValue,
+    const DBusMapping& dbusMapping)
+{
+    try
+    {
+        auto propertyValue = dBusIntf.getDbusPropertyVariant(
+            dbusMapping.objectPath.c_str(), dbusMapping.propertyName.c_str(),
+            dbusMapping.interface.c_str());
+
+        for (const auto& stateValue : stateToDbusValue)
+        {
+            if (stateValue.second == propertyValue)
+            {
+                return stateValue.first;
+            }
+        }
+    }
+    catch (const std::exception& e)
+    {
+        std::cerr << e.what() << '\n';
+    }
+
+    return PLDM_SENSOR_DISABLED;
+}
+
+/** @brief Function to get the state sensor readings requested by pldm requester
+ *
+ *  @tparam[in] DBusInterface - DBus interface type
+ *  @tparam[in] Handler - pldm::responder::platform::Handler
+ *  @param[in] dBusIntf - The interface object of DBusInterface
+ *  @param[in] handler - The interface object of
+ *             pldm::responder::platform::Handler
+ *  @param[in] sensorId - Sensor ID sent by the requester to act on
+ *  @param[in] sensorRearmCnt - Each bit location in this field corresponds to a
+ *              particular sensor within the state sensor
+ *  @param[out] compSensorCnt - composite sensor count
+ *  @param[out] stateField - The state field data for each of the states,
+ *              equal to composite sensor count in number
+ *  @return - Success or failure in setting the states. Returns failure in
+ * terms of PLDM completion codes if atleast one state fails to be set
+ */
+template <class DBusInterface, class Handler>
+int getStateSensorReadingsHandler(
+    const DBusInterface& dBusIntf, Handler& handler, uint16_t sensorId,
+    uint8_t sensorRearmCnt, uint8_t& compSensorCnt,
+    std::vector<get_sensor_state_field>& stateField)
+{
+    using namespace pldm::responder::pdr;
+    using namespace pldm::utils;
+
+    pldm_state_sensor_pdr* pdr = nullptr;
+
+    std::unique_ptr<pldm_pdr, decltype(&pldm_pdr_destroy)> stateSensorPdrRepo(
+        pldm_pdr_init(), pldm_pdr_destroy);
+    Repo stateSensorPDRs(stateSensorPdrRepo.get());
+    getRepoByType(handler.getRepo(), stateSensorPDRs, PLDM_STATE_SENSOR_PDR);
+    if (stateSensorPDRs.empty())
+    {
+        std::cerr << "Failed to get record by PDR type\n";
+        return PLDM_PLATFORM_INVALID_SENSOR_ID;
+    }
+
+    PdrEntry pdrEntry{};
+    auto pdrRecord = stateSensorPDRs.getFirstRecord(pdrEntry);
+    while (pdrRecord)
+    {
+        pdr = reinterpret_cast<pldm_state_sensor_pdr*>(pdrEntry.data);
+        assert(pdr != NULL);
+        if (pdr->sensor_id != sensorId)
+        {
+            pdr = nullptr;
+            pdrRecord = stateSensorPDRs.getNextRecord(pdrRecord, pdrEntry);
+            continue;
+        }
+
+        compSensorCnt = pdr->composite_sensor_count;
+        if (sensorRearmCnt > compSensorCnt)
+        {
+            std::cerr << "The requester sent wrong sensorRearm"
+                      << " count for the sensor, SENSOR_ID=" << sensorId
+                      << "SENSOR_REARM_COUNT=" << sensorRearmCnt << "\n";
+            return PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE;
+        }
+        break;
+    }
+
+    if (!pdr)
+    {
+        return PLDM_PLATFORM_INVALID_SENSOR_ID;
+    }
+
+    int rc = PLDM_SUCCESS;
+    try
+    {
+        const auto& [dbusMappings, dbusValMaps] =
+            handler.getDbusObjMaps(sensorId, TypeId::PLDM_SENSOR_ID);
+
+        stateField.clear();
+        for (size_t i = 0; i < compSensorCnt; i++)
+        {
+            auto& dbusMapping = dbusMappings[i];
+
+            uint8_t sensorOpState = getStateSensorEventState<DBusInterface>(
+                dBusIntf, dbusValMaps[i], dbusMapping);
+            stateField.push_back({PLDM_SENSOR_ENABLED, PLDM_SENSOR_UNKNOWN,
+                                  PLDM_SENSOR_UNKNOWN, sensorOpState});
+        }
+    }
+    catch (const std::out_of_range& e)
+    {
+        std::cerr << "the sensorId does not exist. sensor id: " << sensorId
+                  << e.what() << '\n';
+        rc = PLDM_ERROR;
+    }
+
+    return rc;
+}
+
+} // namespace platform_state_sensor
+} // namespace responder
+} // namespace pldm