sensor_utils: add sensor properties

Add support for ReadingBasis and Implementation sensor properties. These
properties are defined on xyz.openbmc_project.Sensor.Type which will be
optionally implemented by sensor.

DBus Interface definition
- https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/81658

Link to Redfish schema
- https://redfish.dmtf.org/schemas/v1/Sensor.v1_11_0.yaml

Tested: Build an image for gb200nvl-obmc machine with the following
patches cherry picked. This patches are needed to enable the mctp stack.

https://gerrit.openbmc.org/c/openbmc/openbmc/+/79422

Redfish service validator is passing.

```
> curl -s -k -u 'root:0penBmc' https://10.137.203.137/redfish/v1/Chassis/NVIDIA_GB200_1/Sensors/temperature_NVIDIA_GB200_GPU_0_TEMP_1
{
  "@odata.id": "/redfish/v1/Chassis/NVIDIA_GB200_1/Sensors/temperature_NVIDIA_GB200_GPU_0_TEMP_1",
  "@odata.type": "#Sensor.v1_2_0.Sensor",
  "Description": "Thermal Limit(TLIMIT) Temperature is the distance in deg C from the GPU temperature to the first throttle limit.",
  "Id": "temperature_NVIDIA_GB200_GPU_0_TEMP_1",
  "Implementation": "Synthesized",
  "Name": "NVIDIA GB200 GPU 0 TEMP 1",
  "Reading": 56.59375,
  "ReadingBasis": "Headroom",
  "ReadingRangeMax": 127.0,
  "ReadingRangeMin": -128.0,
  "ReadingType": "Temperature",
  "ReadingUnits": "Cel",
  "Status": {
    "Health": "OK",
    "State": "Enabled"
  }
}%

root@gb200nvl-obmc:~# busctl introspect xyz.openbmc_project.GpuSensor /xyz/openbmc_project/sensors/temperature/NVIDIA_GB200_GPU_0_TEMP_1
NAME                                                  TYPE      SIGNATURE RESULT/VALUE                             FLAGS
org.freedesktop.DBus.Introspectable                   interface -         -                                        -
.Introspect                                           method    -         s                                        -
org.freedesktop.DBus.Peer                             interface -         -                                        -
.GetMachineId                                         method    -         s                                        -
.Ping                                                 method    -         -                                        -
org.freedesktop.DBus.Properties                       interface -         -                                        -
.Get                                                  method    ss        v                                        -
.GetAll                                               method    s         a{sv}                                    -
.Set                                                  method    ssv       -                                        -
.PropertiesChanged                                    signal    sa{sv}as  -                                        -
xyz.openbmc_project.Association.Definitions           interface -         -                                        -
.Associations                                         property  a(sss)    1 "chassis" "all_sensors" "/xyz/openb... emits-change
xyz.openbmc_project.Inventory.Item                    interface -         -                                        -
.PrettyName                                           property  s         "Thermal Limit(TLIMIT) Temperature is... emits-change
xyz.openbmc_project.Sensor.Type                       interface -         -                                        -
.Implementation                                       property  s         "xyz.openbmc_project.Sensor.Type.Impl... emits-change
.ReadingBasis                                         property  s         "xyz.openbmc_project.Sensor.Type.Read... emits-change
xyz.openbmc_project.Sensor.Value                      interface -         -                                        -
.MaxValue                                             property  d         127                                      emits-change
.MinValue                                             property  d         -128                                     emits-change
.Unit                                                 property  s         "xyz.openbmc_project.Sensor.Value.Uni... emits-change
.Value                                                property  d         56.6836                                  emits-change writable
xyz.openbmc_project.Sensor.ValueMutability            interface -         -                                        -
.Mutable                                              property  b         true                                     emits-change
xyz.openbmc_project.State.Decorator.Availability      interface -         -                                        -
.Available                                            property  b         true                                     emits-change writable
xyz.openbmc_project.State.Decorator.OperationalStatus interface -         -                                        -
.Functional                                           property  b         true                                     emits-change
```

Change-Id: I61344e8d8c8ef36d7553f33afb5f84643ce1fe4d
Signed-off-by: Harshit Aghera <haghera@nvidia.com>
diff --git a/docs/Redfish.md b/docs/Redfish.md
index 5a2b32c..1d6d34c 100644
--- a/docs/Redfish.md
+++ b/docs/Redfish.md
@@ -290,7 +290,9 @@
 
 #### Sensor
 
+- Implementation
 - Reading
+- ReadingBasis
 - ReadingRangeMax
 - ReadingRangeMin
 - ReadingType
diff --git a/redfish-core/include/utils/sensor_utils.hpp b/redfish-core/include/utils/sensor_utils.hpp
index f1adafe..f97d93f 100644
--- a/redfish-core/include/utils/sensor_utils.hpp
+++ b/redfish-core/include/utils/sensor_utils.hpp
@@ -417,6 +417,49 @@
     }
 }
 
+inline sensor::ReadingBasisType dBusSensorReadingBasisToRedfish(
+    const std::string& readingBasis)
+{
+    if (readingBasis ==
+        "xyz.openbmc_project.Sensor.Type.ReadingBasisType.Headroom")
+    {
+        return sensor::ReadingBasisType::Headroom;
+    }
+    if (readingBasis ==
+        "xyz.openbmc_project.Sensor.Type.ReadingBasisType.Delta")
+    {
+        return sensor::ReadingBasisType::Delta;
+    }
+    if (readingBasis == "xyz.openbmc_project.Sensor.Type.ReadingBasisType.Zero")
+    {
+        return sensor::ReadingBasisType::Zero;
+    }
+
+    return sensor::ReadingBasisType::Invalid;
+}
+
+inline sensor::ImplementationType dBusSensorImplementationToRedfish(
+    const std::string& implementation)
+{
+    if (implementation ==
+        "xyz.openbmc_project.Sensor.Type.ImplementationType.Physical")
+    {
+        return sensor::ImplementationType::PhysicalSensor;
+    }
+    if (implementation ==
+        "xyz.openbmc_project.Sensor.Type.ImplementationType.Synthesized")
+    {
+        return sensor::ImplementationType::Synthesized;
+    }
+    if (implementation ==
+        "xyz.openbmc_project.Sensor.Type.ImplementationType.Reported")
+    {
+        return sensor::ImplementationType::Reported;
+    }
+
+    return sensor::ImplementationType::Invalid;
+}
+
 /**
  * @brief Builds a json sensor representation of a sensor.
  * @param sensorName  The name of the sensor to be built
@@ -474,9 +517,13 @@
 
         const bool* checkAvailable = nullptr;
         bool available = true;
+        std::optional<std::string> readingBasis;
+        std::optional<std::string> implementation;
+
         const bool success = sdbusplus::unpackPropertiesNoThrow(
             dbus_utils::UnpackErrorPrinter(), propertiesDict, "Available",
-            checkAvailable);
+            checkAvailable, "ReadingBasis", readingBasis, "Implementation",
+            implementation);
         if (!success)
         {
             messages::internalError();
@@ -492,7 +539,7 @@
 
         if (chassisSubNode == ChassisSubNode::sensorsNode)
         {
-            sensorJson["@odata.type"] = "#Sensor.v1_2_0.Sensor";
+            sensorJson["@odata.type"] = "#Sensor.v1_11_0.Sensor";
 
             sensor::ReadingType readingType =
                 sensors::toReadingType(sensorType);
@@ -516,6 +563,26 @@
             {
                 sensorJson["ReadingUnits"] = readingUnits;
             }
+
+            if (readingBasis.has_value())
+            {
+                sensor::ReadingBasisType readingBasisOpt =
+                    dBusSensorReadingBasisToRedfish(*readingBasis);
+                if (readingBasisOpt != sensor::ReadingBasisType::Invalid)
+                {
+                    sensorJson["ReadingBasis"] = readingBasisOpt;
+                }
+            }
+
+            if (implementation.has_value())
+            {
+                sensor::ImplementationType implementationOpt =
+                    dBusSensorImplementationToRedfish(*implementation);
+                if (implementationOpt != sensor::ImplementationType::Invalid)
+                {
+                    sensorJson["Implementation"] = implementationOpt;
+                }
+            }
         }
         else if (sensorType == "temperature")
         {