sensor: Implement sensor "PRIORITY"

This commit introduces the `xyz.openbmc_project.Common.Priority`
interface to define the priority of sensors. If a sensor's priority
attribute is specified, this interface is created with the 'priority'
attribute. However, if the priority attribute is not specified, this
interface is not created.

The `xyz.openbmc_project.Common.Priority` interface is used to indicate
the priority level of fan sensors. It provides information about
primary and secondary RPM sensors for dual rotor fans, allowing for a
more specific description of the sensor's priority.

phosphor-dbus-interfaces commit:
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/66779

Tested: Build phosphor-hwmon successfully

'''
1. Retrieve the priority level of the secondary sensor

busctl introspect xyz.openbmc_project.Hwmon-xxx .Hwmon1 \
/xyz/openbmc_project/sensors/fan_tach/fan1_1  xyz.openbmc_project.Common.Priority

NAME                                TYPE      SIGNATURE RESULT/VALUE FLAGS
.Priority                           property  u         1            emits-change writable

2. If the "PRIORITY" is not specified in the sensor's configuration file

busctl introspect xyz.openbmc_project.Hwmon-xxx .Hwmon1 \
/xyz/openbmc_project/sensors/fan_tach/fan1_0  xyz.openbmc_project.Common.Priority
NAME TYPE SIGNATURE RESULT/VALUE FLAGS

3. Change the sensor priority

busctl set-property xyz.openbmc_project.Hwmon-xxx.Hwmon1 \
/xyz/openbmc_project/sensors/fan_tach/fan1_1 xyz.openbmc_project.Common.Priority \
 Priority u 0

busctl introspect xyz.openbmc_project.Hwmon-xxx .Hwmon1 \
/xyz/openbmc_project/sensors/fan_tach/fan1_1  xyz.openbmc_project.Common.Priority
NAME                                TYPE      SIGNATURE RESULT/VALUE FLAGS
.Priority                           property  u         0            emits-change writable
'''

Change-Id: I7a226cf105756bc32e04f6724428d93e84dfb72a
Signed-off-by: Lakshmi Yadlapati <lakshmiy@us.ibm.com>
diff --git a/interface.hpp b/interface.hpp
index 6e2d71d..234af4c 100644
--- a/interface.hpp
+++ b/interface.hpp
@@ -1,6 +1,7 @@
 #pragma once
 
 #include <sdbusplus/server.hpp>
+#include <xyz/openbmc_project/Common/Priority/server.hpp>
 #include <xyz/openbmc_project/Control/FanPwm/server.hpp>
 #include <xyz/openbmc_project/Control/FanSpeed/server.hpp>
 #include <xyz/openbmc_project/Sensor/Accuracy/server.hpp>
@@ -29,6 +30,9 @@
 using StatusInterface = sdbusplus::xyz::openbmc_project::State::Decorator::
     server::OperationalStatus;
 using StatusObject = ServerObject<StatusInterface>;
+using PriorityInterface =
+    sdbusplus::xyz::openbmc_project::Common::server::Priority;
+using PriorityObject = ServerObject<PriorityInterface>;
 
 using SensorValueType = double;
 
@@ -45,6 +49,7 @@
     FAN_PWM,
     STATUS,
     ACCURACY,
+    PRIORITY,
 };
 
 // vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
diff --git a/mainloop.cpp b/mainloop.cpp
index e38b156..cfc5b5e 100644
--- a/mainloop.cpp
+++ b/mainloop.cpp
@@ -176,16 +176,18 @@
     std::string id = getID(sensor);
     std::string label;
     std::string accuracy;
+    std::string priority;
 
     if (!id.empty())
     {
         // Ignore inputs without a label.
         label = env::getEnv("LABEL", sensor.first.first, id);
         accuracy = env::getEnv("ACCURACY", sensor.first.first, id);
+        priority = env::getEnv("PRIORITY", sensor.first.first, id);
     }
 
-    return std::make_tuple(std::move(id), std::move(label),
-                           std::move(accuracy));
+    return std::make_tuple(std::move(id), std::move(label), std::move(accuracy),
+                           std::move(priority));
 }
 
 /**
@@ -254,6 +256,19 @@
         catch (const std::invalid_argument&)
         {}
 
+        // Add priority interface
+        auto priorityStr = std::get<sensorPriority>(properties);
+        try
+        {
+            if (!priorityStr.empty())
+            {
+                auto priority = std::stoul(priorityStr);
+                sensorObj->addPriority(info, priority);
+            }
+        }
+        catch (const std::invalid_argument&)
+        {}
+
         // Add status interface based on _fault file being present
         sensorObj->addStatus(info);
         valueInterface = sensorObj->addValue(retryIO, info, _timedoutMap);
diff --git a/mainloop.hpp b/mainloop.hpp
index cc8de94..6ce02a2 100644
--- a/mainloop.hpp
+++ b/mainloop.hpp
@@ -25,7 +25,9 @@
 static constexpr auto sensorID = 0;
 static constexpr auto sensorLabel = 1;
 static constexpr auto sensorAccuracy = 2;
-using SensorIdentifiers = std::tuple<std::string, std::string, std::string>;
+static constexpr auto sensorPriority = 3;
+using SensorIdentifiers =
+    std::tuple<std::string, std::string, std::string, std::string>;
 
 /** @class MainLoop
  *  @brief hwmon-readd main application loop.
diff --git a/sensor.cpp b/sensor.cpp
index e53b01c..0b3ca66 100644
--- a/sensor.cpp
+++ b/sensor.cpp
@@ -280,6 +280,22 @@
     return iface;
 }
 
+std::shared_ptr<PriorityObject> Sensor::addPriority(ObjectInfo& info,
+                                                    size_t priority)
+{
+    auto& objPath = std::get<std::string>(info);
+    auto& obj = std::get<InterfaceMap>(info);
+
+    auto& bus = *std::get<sdbusplus::bus_t*>(info);
+    auto iface = std::make_shared<PriorityObject>(
+        bus, objPath.c_str(), PriorityObject::action::emit_no_signals);
+
+    iface->priority(priority);
+    obj[InterfaceType::PRIORITY] = iface;
+
+    return iface;
+}
+
 void gpioLock(const gpioplus::HandleInterface*&& handle)
 {
     handle->setValues({0});
diff --git a/sensor.hpp b/sensor.hpp
index 6f7aa59..ac38cff 100644
--- a/sensor.hpp
+++ b/sensor.hpp
@@ -138,6 +138,19 @@
                                                 double accuracy);
 
     /**
+     * @brief Add Priority interface and priority property for sensors
+     * @details The Priority interface defines priority levels for sensors.
+     *
+     * @param[in] info     - Sensor object information
+     * @param[in] priority - The priority level for the sensor
+     *
+     * @return - Shared pointer to the priority object
+     */
+
+    std::shared_ptr<PriorityObject> addPriority(ObjectInfo& info,
+                                                size_t priority);
+
+    /**
      * @brief Get the scale from the sensor.
      *
      * @return - Scale value